blob: 9e0c8ef7cffc77f48956cae524939d116db4b30c [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010020 */
21
22/*
23 * References:
24 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010026 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010027 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010028 * RFC 4492 for the related TLS structures and constants
Nicholas Wilson08f3ef12015-11-10 13:10:01 +000029 * RFC 7748 for the Curve448 and Curve25519 curve definitions
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020030 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020031 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010032 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020033 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020034 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
35 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
36 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010037 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020038 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010039 * render ECC resistant against Side Channel Attacks. IACR Cryptology
40 * ePrint Archive, 2004, vol. 2004, p. 342.
41 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010042 */
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020046#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020048#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010049
Janos Follath683c5822018-12-07 12:09:25 +000050/**
51 * \brief Function level alternative implementation.
52 *
53 * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
54 * replace certain functions in this module. The alternative implementations are
55 * typically hardware accelerators and need to activate the hardware before the
56 * computation starts and deactivate it after it finishes. The
57 * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
58 * this purpose.
59 *
60 * To preserve the correct functionality the following conditions must hold:
61 *
62 * - The alternative implementation must be activated by
63 * mbedtls_internal_ecp_init() before any of the replaceable functions is
64 * called.
65 * - mbedtls_internal_ecp_free() must \b only be called when the alternative
66 * implementation is activated.
67 * - mbedtls_internal_ecp_init() must \b not be called when the alternative
68 * implementation is activated.
69 * - Public functions must not return while the alternative implementation is
70 * activated.
71 * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
72 * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
73 * \endcode ensures that the alternative implementation supports the current
74 * group.
75 */
76#if defined(MBEDTLS_ECP_INTERNAL_ALT)
77#endif
78
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010080
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000081#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000082#include "mbedtls/threading.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050083#include "mbedtls/platform_util.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020084
Rich Evans00ab4702015-02-06 13:43:58 +000085#include <string.h>
86
Janos Follathb0697532016-08-18 12:38:46 +010087#if !defined(MBEDTLS_ECP_ALT)
88
Hanno Becker4f8e8e52018-12-14 15:08:03 +000089/* Parameter validation macros based on platform_util.h */
90#define ECP_VALIDATE_RET( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
92#define ECP_VALIDATE( cond ) \
93 MBEDTLS_INTERNAL_VALIDATE( cond )
94
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020095#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000096#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020097#else
Rich Evans00ab4702015-02-06 13:43:58 +000098#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000099#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200101#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200102#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +0200103#endif
104
Janos Follath47d28f02016-11-01 13:22:05 +0000105#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +0100106
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200107#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200108#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200109#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200110#elif defined(MBEDTLS_CTR_DRBG_C)
111#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200112#elif defined(MBEDTLS_SHA512_C)
113#include "mbedtls/sha512.h"
114#elif defined(MBEDTLS_SHA256_C)
115#include "mbedtls/sha256.h"
116#elif defined(MBEDTLS_SHA1_C)
117#include "mbedtls/sha1.h"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200118#else
119#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
120#endif
121#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
122
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100123#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
124 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100125#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200126#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100129/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100130 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200131 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100132 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100133static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100134#endif
135
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200136#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
137/*
138 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200139 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200140 * that people will pass non-NULL RNG when they care about side-channels, but
141 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
142 * no opportunity for the user to do anything about it.
143 *
144 * The obvious strategies for addressing that include:
145 * - change those APIs so that they take RNG arguments;
146 * - require a global RNG to be available to all crypto modules.
147 *
148 * Unfortunately those would break compatibility. So what we do instead is
149 * have our own internal DRBG instance, seeded from the secret scalar.
150 *
151 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200152 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200153 */
154
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200155#if defined(MBEDTLS_HMAC_DRBG_C)
156
157/* DRBG context type */
158typedef mbedtls_hmac_drbg_context ecp_drbg_context;
159
160/* DRBG context init */
161static inline void ecp_drbg_init( ecp_drbg_context *ctx )
162{
163 mbedtls_hmac_drbg_init( ctx );
164}
165
166/* DRBG context free */
167static inline void ecp_drbg_free( ecp_drbg_context *ctx )
168{
169 mbedtls_hmac_drbg_free( ctx );
170}
171
172/* DRBG function */
173static inline int ecp_drbg_random( void *p_rng,
174 unsigned char *output, size_t output_len )
175{
176 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
177}
178
179/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200180static int ecp_drbg_seed( ecp_drbg_context *ctx,
181 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200182{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200183 int ret;
184 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200185 /* The list starts with strong hashes */
186 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
187 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
188
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200189 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
190 secret_bytes, secret_len ) );
191
192 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
193
194cleanup:
195 mbedtls_platform_zeroize( secret_bytes, secret_len );
196
197 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200198}
199
200#elif defined(MBEDTLS_CTR_DRBG_C)
201
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200202/* DRBG context type */
203typedef mbedtls_ctr_drbg_context ecp_drbg_context;
204
205/* DRBG context init */
206static inline void ecp_drbg_init( ecp_drbg_context *ctx )
207{
208 mbedtls_ctr_drbg_init( ctx );
209}
210
211/* DRBG context free */
212static inline void ecp_drbg_free( ecp_drbg_context *ctx )
213{
214 mbedtls_ctr_drbg_free( ctx );
215}
216
217/* DRBG function */
218static inline int ecp_drbg_random( void *p_rng,
219 unsigned char *output, size_t output_len )
220{
221 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
222}
223
224/*
225 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
226 * we need to pass an entropy function when seeding. So we use a dummy
227 * function for that, and pass the actual entropy as customisation string.
228 * (During seeding of CTR_DRBG the entropy input and customisation string are
229 * concatenated before being used to update the secret state.)
230 */
231static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
232{
233 (void) ctx;
234 memset( out, 0, len );
235 return( 0 );
236}
237
238/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200239static int ecp_drbg_seed( ecp_drbg_context *ctx,
240 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200241{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200242 int ret;
243 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200244
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200245 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
246 secret_bytes, secret_len ) );
247
248 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
249 secret_bytes, secret_len );
250
251cleanup:
252 mbedtls_platform_zeroize( secret_bytes, secret_len );
253
254 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200255}
256
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200257#elif defined(MBEDTLS_SHA512_C) || \
258 defined(MBEDTLS_SHA256_C) || \
259 defined(MBEDTLS_SHA1_C)
260
261/* This will be used in the self-test function */
262#define ECP_ONE_STEP_KDF
263
264/*
265 * We need to expand secret data (the scalar) into a longer stream of bytes.
266 *
267 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
268 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
269 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
270 *
271 * We need a basic hash abstraction layer to use whatever SHA is available.
272 */
273#if defined(MBEDTLS_SHA512_C)
274
275#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
276#define HASH_BLOCK_BYTES ( 512 / 8 )
277
278#elif defined(MBEDTLS_SHA256_C)
279
280#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
281#define HASH_BLOCK_BYTES ( 256 / 8 )
282
283#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
284
285#define HASH_FUNC mbedtls_sha1_ret
286#define HASH_BLOCK_BYTES ( 160 / 8 )
287
288#endif /* SHA512/SHA256/SHA1 abstraction */
289
290/*
291 * State consists of a 32-bit counter plus the secret value.
292 *
293 * We stored them concatenated in a single buffer as that's what will get
294 * passed to the hash function.
295 */
296typedef struct {
297 size_t total_len;
298 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
299} ecp_drbg_context;
300
301static void ecp_drbg_init( ecp_drbg_context *ctx )
302{
303 memset( ctx, 0, sizeof( ecp_drbg_context ) );
304}
305
306static void ecp_drbg_free( ecp_drbg_context *ctx )
307{
308 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
309}
310
311static int ecp_drbg_seed( ecp_drbg_context *ctx,
312 const mbedtls_mpi *secret, size_t secret_len )
313{
314 ctx->total_len = 4 + secret_len;
315 memset( ctx->buf, 0, 4);
316 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
317}
318
319static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
320{
321 ecp_drbg_context *ctx = p_rng;
322 int ret;
323 size_t len_done = 0;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200324 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200325
326 while( len_done < output_len )
327 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200328 uint8_t use_len;
329
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200330 /* This function is only called for coordinate randomisation, which
331 * happens only twice in a scalar multiplication. Each time needs a
332 * random value in the range [2, p-1], and gets it by drawing len(p)
333 * bytes from this function, and retrying up to 10 times if unlucky.
334 *
335 * So for the largest curve, each scalar multiplication draws at most
336 * 2 * 66 bytes. The minimum block size is 20 bytes (with SHA-1), so
337 * that means at most 66 blocks.
338 *
339 * Since we don't need to draw more that 255 blocks, don't bother
340 * with carry propagation and just return an error instead. We can
341 * change that it we even need to draw more blinding values.
342 */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200343 ctx->buf[3] += 1;
344 if( ctx->buf[3] == 0 )
345 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
346
347 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
348 if( ret != 0 )
349 return( ret );
350
351 if( output_len - len_done > HASH_BLOCK_BYTES )
352 use_len = HASH_BLOCK_BYTES;
353 else
354 use_len = output_len - len_done;
355
356 memcpy( output + len_done, tmp, use_len );
357 len_done += use_len;
358 }
359
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200360 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
361
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200362 return( 0 );
363}
364
365#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200366#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200367#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200368#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
369
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200370#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100371/*
372 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200373 *
374 * Default value 0 means that ECC operations will not yield.
375 * Note that regardless of the value of ecp_max_ops, always at
376 * least one step is performed before yielding.
377 *
378 * Setting ecp_max_ops=1 can be suitable for testing purposes
379 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100380 */
381static unsigned ecp_max_ops = 0;
382
383/*
384 * Set ecp_max_ops
385 */
386void mbedtls_ecp_set_max_ops( unsigned max_ops )
387{
388 ecp_max_ops = max_ops;
389}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100390
391/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200392 * Check if restart is enabled
393 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200394int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200395{
396 return( ecp_max_ops != 0 );
397}
398
399/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200400 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100401 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200402struct mbedtls_ecp_restart_mul
403{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100404 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100405 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100406 mbedtls_ecp_point *T; /* table for precomputed points */
407 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200408 enum { /* what were we doing last time we returned? */
409 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
410 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100411 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
412 ecp_rsm_pre_add, /* precompute remaining points by adding */
413 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200414 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100415 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100416 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200417#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
418 ecp_drbg_context drbg_ctx;
419 unsigned char drbg_seeded;
420#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100421};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100422
423/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200424 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100425 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200426static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100427{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200428 mbedtls_ecp_point_init( &ctx->R );
429 ctx->i = 0;
430 ctx->T = NULL;
431 ctx->T_size = 0;
432 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200433#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
434 ecp_drbg_init( &ctx->drbg_ctx );
435 ctx->drbg_seeded = 0;
436#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100437}
438
439/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200440 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100441 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200442static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100443{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100444 unsigned char i;
445
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100446 if( ctx == NULL )
447 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100448
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100449 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100450
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200451 if( ctx->T != NULL )
452 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100453 for( i = 0; i < ctx->T_size; i++ )
454 mbedtls_ecp_point_free( ctx->T + i );
455 mbedtls_free( ctx->T );
456 }
457
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200458#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
459 ecp_drbg_free( &ctx->drbg_ctx );
460#endif
461
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200462 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100463}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100464
465/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200466 * Restart context for ecp_muladd()
467 */
468struct mbedtls_ecp_restart_muladd
469{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200470 mbedtls_ecp_point mP; /* mP value */
471 mbedtls_ecp_point R; /* R intermediate result */
472 enum { /* what should we do next? */
473 ecp_rsma_mul1 = 0, /* first multiplication */
474 ecp_rsma_mul2, /* second multiplication */
475 ecp_rsma_add, /* addition */
476 ecp_rsma_norm, /* normalization */
477 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200478};
479
480/*
481 * Init restart_muladd sub-context
482 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200483static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200484{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200485 mbedtls_ecp_point_init( &ctx->mP );
486 mbedtls_ecp_point_init( &ctx->R );
487 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200488}
489
490/*
491 * Free the components of a restart_muladd sub-context
492 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200493static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200494{
495 if( ctx == NULL )
496 return;
497
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200498 mbedtls_ecp_point_free( &ctx->mP );
499 mbedtls_ecp_point_free( &ctx->R );
500
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200501 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200502}
503
504/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200505 * Initialize a restart context
506 */
507void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
508{
Hanno Becker80f71682018-12-18 23:44:43 +0000509 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200510 ctx->ops_done = 0;
511 ctx->depth = 0;
512 ctx->rsm = NULL;
513 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200514}
515
516/*
517 * Free the components of a restart context
518 */
519void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
520{
521 if( ctx == NULL )
522 return;
523
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200524 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200525 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200526
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200527 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200528 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200529
530 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200531}
532
533/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100534 * Check if we can do the next step
535 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200536int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
537 mbedtls_ecp_restart_ctx *rs_ctx,
538 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100539{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000540 ECP_VALIDATE_RET( grp != NULL );
541
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200542 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100543 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100544 /* scale depending on curve size: the chosen reference is 256-bit,
545 * and multiplication is quadratic. Round to the closest integer. */
546 if( grp->pbits >= 512 )
547 ops *= 4;
548 else if( grp->pbits >= 384 )
549 ops *= 2;
550
Hanno Beckerb10c6602018-10-26 13:50:13 +0100551 /* Avoid infinite loops: always allow first step.
552 * Because of that, however, it's not generally true
553 * that ops_done <= ecp_max_ops, so the check
554 * ops_done > ecp_max_ops below is mandatory. */
555 if( ( rs_ctx->ops_done != 0 ) &&
556 ( rs_ctx->ops_done > ecp_max_ops ||
557 ops > ecp_max_ops - rs_ctx->ops_done ) )
558 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100559 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100560 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100561
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100562 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200563 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100564 }
565
566 return( 0 );
567}
568
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200569/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200570#define ECP_RS_ENTER( SUB ) do { \
571 /* reset ops count for this call if top-level */ \
572 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
573 rs_ctx->ops_done = 0; \
574 \
575 /* set up our own sub-context if needed */ \
576 if( mbedtls_ecp_restart_is_enabled() && \
577 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
578 { \
579 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
580 if( rs_ctx->SUB == NULL ) \
581 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
582 \
583 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
584 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200585} while( 0 )
586
587/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200588#define ECP_RS_LEAVE( SUB ) do { \
589 /* clear our sub-context when not in progress (done or error) */ \
590 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
591 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
592 { \
593 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
594 mbedtls_free( rs_ctx->SUB ); \
595 rs_ctx->SUB = NULL; \
596 } \
597 \
598 if( rs_ctx != NULL ) \
599 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200600} while( 0 )
601
602#else /* MBEDTLS_ECP_RESTARTABLE */
603
604#define ECP_RS_ENTER( sub ) (void) rs_ctx;
605#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
606
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200607#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
610 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
611 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
612 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
613 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
614 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
615 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
616 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
617 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
618 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
619 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200620#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100621#endif
622
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000623#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
624 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200625#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100626#endif
627
628/*
629 * Curve types: internal for now, might be exposed later
630 */
631typedef enum
632{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200633 ECP_TYPE_NONE = 0,
634 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
635 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100636} ecp_curve_type;
637
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100638/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200639 * List of supported curves:
640 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200641 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200642 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200643 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100644 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100645 * Curves are listed in order: largest curves first, and for a given size,
646 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200647 *
648 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200651{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
653 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200654#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
656 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100657#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
659 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200660#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
662 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100663#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
665 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
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_SECP256K1_ENABLED)
668 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100669#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
671 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100672#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
674 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200675#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
677 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100678#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
680 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100681#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
683 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100684#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200686};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100687
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200688#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
689 sizeof( ecp_supported_curves[0] )
690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200692
693/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200694 * List of supported curves and associated info
695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200697{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200698 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200699}
700
701/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100702 * List of supported curves, group ID only
703 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100705{
706 static int init_done = 0;
707
708 if( ! init_done )
709 {
710 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100712
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 for( curve_info = mbedtls_ecp_curve_list();
714 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100715 curve_info++ )
716 {
717 ecp_supported_grp_id[i++] = curve_info->grp_id;
718 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100720
721 init_done = 1;
722 }
723
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200724 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100725}
726
727/*
728 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200729 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730const 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 +0200731{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 for( curve_info = mbedtls_ecp_curve_list();
735 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200736 curve_info++ )
737 {
738 if( curve_info->grp_id == grp_id )
739 return( curve_info );
740 }
741
742 return( NULL );
743}
744
745/*
746 * Get the curve info from the TLS identifier
747 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200749{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 for( curve_info = mbedtls_ecp_curve_list();
753 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200754 curve_info++ )
755 {
756 if( curve_info->tls_id == tls_id )
757 return( curve_info );
758 }
759
760 return( NULL );
761}
762
763/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100764 * Get the curve info from the name
765 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100767{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100769
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000770 if( name == NULL )
771 return( NULL );
772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200773 for( curve_info = mbedtls_ecp_curve_list();
774 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100775 curve_info++ )
776 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200777 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100778 return( curve_info );
779 }
780
781 return( NULL );
782}
783
784/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100785 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100786 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100788{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100789 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200790 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100791
792 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200793 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100794 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200795 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100796}
797
798/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100799 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100800 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100802{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000803 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100804
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 mbedtls_mpi_init( &pt->X );
806 mbedtls_mpi_init( &pt->Y );
807 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100808}
809
810/*
811 * Initialize (the components of) a group
812 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100814{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000815 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100816
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200817 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200818 mbedtls_mpi_init( &grp->P );
819 mbedtls_mpi_init( &grp->A );
820 mbedtls_mpi_init( &grp->B );
821 mbedtls_ecp_point_init( &grp->G );
822 mbedtls_mpi_init( &grp->N );
823 grp->pbits = 0;
824 grp->nbits = 0;
825 grp->h = 0;
826 grp->modp = NULL;
827 grp->t_pre = NULL;
828 grp->t_post = NULL;
829 grp->t_data = NULL;
830 grp->T = NULL;
831 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100832}
833
834/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200835 * Initialize (the components of) a key pair
836 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200838{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000839 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_ecp_group_init( &key->grp );
842 mbedtls_mpi_init( &key->d );
843 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200844}
845
846/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100847 * Unallocate (the components of) a point
848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200849void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100850{
851 if( pt == NULL )
852 return;
853
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854 mbedtls_mpi_free( &( pt->X ) );
855 mbedtls_mpi_free( &( pt->Y ) );
856 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100857}
858
859/*
860 * Unallocate (the components of) a group
861 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100863{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200864 size_t i;
865
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100866 if( grp == NULL )
867 return;
868
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100869 if( grp->h != 1 )
870 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 mbedtls_mpi_free( &grp->P );
872 mbedtls_mpi_free( &grp->A );
873 mbedtls_mpi_free( &grp->B );
874 mbedtls_ecp_point_free( &grp->G );
875 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100876 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200877
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200878 if( grp->T != NULL )
879 {
880 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 mbedtls_ecp_point_free( &grp->T[i] );
882 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200883 }
884
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500885 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100886}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100887
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100888/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200889 * Unallocate (the components of) a key pair
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200892{
Paul Bakker66d5d072014-06-17 16:39:18 +0200893 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200894 return;
895
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 mbedtls_ecp_group_free( &key->grp );
897 mbedtls_mpi_free( &key->d );
898 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200899}
900
901/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200902 * Copy the contents of a point
903 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200905{
906 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000907 ECP_VALIDATE_RET( P != NULL );
908 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200909
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
911 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
912 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200913
914cleanup:
915 return( ret );
916}
917
918/*
919 * Copy the contents of a group object
920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200922{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000923 ECP_VALIDATE_RET( dst != NULL );
924 ECP_VALIDATE_RET( src != NULL );
925
926 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200927}
928
929/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100930 * Set point to zero
931 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100933{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100934 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000935 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100936
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
938 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
939 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100940
941cleanup:
942 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100943}
944
945/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100946 * Tell if a point is zero
947 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100949{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000950 ECP_VALIDATE_RET( pt != NULL );
951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100953}
954
955/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700956 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200957 */
958int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
959 const mbedtls_ecp_point *Q )
960{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000961 ECP_VALIDATE_RET( P != NULL );
962 ECP_VALIDATE_RET( Q != NULL );
963
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200964 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
965 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
966 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
967 {
968 return( 0 );
969 }
970
971 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
972}
973
974/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100975 * Import a non-zero point from ASCII strings
976 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100978 const char *x, const char *y )
979{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100980 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000981 ECP_VALIDATE_RET( P != NULL );
982 ECP_VALIDATE_RET( x != NULL );
983 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100984
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
986 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
987 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100988
989cleanup:
990 return( ret );
991}
992
993/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100994 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100995 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000996int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
997 const mbedtls_ecp_point *P,
998 int format, size_t *olen,
999 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001000{
Paul Bakkera280d0f2013-04-08 13:40:17 +02001001 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001002 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001003 ECP_VALIDATE_RET( grp != NULL );
1004 ECP_VALIDATE_RET( P != NULL );
1005 ECP_VALIDATE_RET( olen != NULL );
1006 ECP_VALIDATE_RET( buf != NULL );
1007 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1008 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001009
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001010 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001011 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001014 {
1015 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001017
1018 buf[0] = 0x00;
1019 *olen = 1;
1020
1021 return( 0 );
1022 }
1023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001027 {
1028 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001029
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001030 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001032
1033 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1035 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001036 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001038 {
1039 *olen = plen + 1;
1040
1041 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1045 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001046 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001047
1048cleanup:
1049 return( ret );
1050}
1051
1052/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001053 * Import a point from unsigned binary data (SEC1 2.3.4)
1054 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001055int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1056 mbedtls_ecp_point *pt,
1057 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001058{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001059 int ret;
1060 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001061 ECP_VALIDATE_RET( grp != NULL );
1062 ECP_VALIDATE_RET( pt != NULL );
1063 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001064
Paul Bakker82788fb2014-10-20 13:59:19 +02001065 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001067
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001068 if( buf[0] == 0x00 )
1069 {
1070 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001072 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001074 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001077
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001078 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001079 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001080
1081 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001082 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001083
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1085 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1086 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001087
1088cleanup:
1089 return( ret );
1090}
1091
1092/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001093 * Import a point from a TLS ECPoint record (RFC 4492)
1094 * struct {
1095 * opaque point <1..2^8-1>;
1096 * } ECPoint;
1097 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001098int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1099 mbedtls_ecp_point *pt,
1100 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001101{
1102 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001103 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001104 ECP_VALIDATE_RET( grp != NULL );
1105 ECP_VALIDATE_RET( pt != NULL );
1106 ECP_VALIDATE_RET( buf != NULL );
1107 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001108
1109 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001110 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001111 */
1112 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001114
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001115 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001116 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001118
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001119 /*
1120 * Save buffer start for read_binary and update buf
1121 */
1122 buf_start = *buf;
1123 *buf += data_len;
1124
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001125 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001126}
1127
1128/*
1129 * Export a point as a TLS ECPoint record (RFC 4492)
1130 * struct {
1131 * opaque point <1..2^8-1>;
1132 * } ECPoint;
1133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001135 int format, size_t *olen,
1136 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001137{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001138 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001139 ECP_VALIDATE_RET( grp != NULL );
1140 ECP_VALIDATE_RET( pt != NULL );
1141 ECP_VALIDATE_RET( olen != NULL );
1142 ECP_VALIDATE_RET( buf != NULL );
1143 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1144 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001145
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001146 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001147 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001148 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001149 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001150 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001153 olen, buf + 1, blen - 1) ) != 0 )
1154 return( ret );
1155
1156 /*
1157 * write length to the first byte and update total length
1158 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001159 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001160 ++*olen;
1161
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001162 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001163}
1164
1165/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001166 * Set a group from an ECParameters record (RFC 4492)
1167 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001168int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1169 const unsigned char **buf, size_t len )
1170{
1171 int ret;
1172 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001173 ECP_VALIDATE_RET( grp != NULL );
1174 ECP_VALIDATE_RET( buf != NULL );
1175 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001176
1177 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1178 return( ret );
1179
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001180 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001181}
1182
1183/*
1184 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1185 * mbedtls_ecp_group_id.
1186 */
1187int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1188 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001189{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001190 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001192 ECP_VALIDATE_RET( grp != NULL );
1193 ECP_VALIDATE_RET( buf != NULL );
1194 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001195
1196 /*
1197 * We expect at least three bytes (see below)
1198 */
1199 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001200 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001201
1202 /*
1203 * First byte is curve_type; only named_curve is handled
1204 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001205 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1206 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001207
1208 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001209 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001210 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001211 tls_id = *(*buf)++;
1212 tls_id <<= 8;
1213 tls_id |= *(*buf)++;
1214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001215 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1216 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001217
Janos Follath89ac8c92018-10-30 11:24:05 +00001218 *grp = curve_info->grp_id;
1219
1220 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001221}
1222
1223/*
1224 * Write the ECParameters record corresponding to a group (RFC 4492)
1225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001226int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001227 unsigned char *buf, size_t blen )
1228{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001230 ECP_VALIDATE_RET( grp != NULL );
1231 ECP_VALIDATE_RET( buf != NULL );
1232 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001233
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1235 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001236
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001237 /*
1238 * We are going to write 3 bytes (see below)
1239 */
1240 *olen = 3;
1241 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001243
1244 /*
1245 * First byte is curve_type, always named_curve
1246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001248
1249 /*
1250 * Next two bytes are the namedcurve value
1251 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001252 buf[0] = curve_info->tls_id >> 8;
1253 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001254
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001255 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001256}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001257
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001258/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1260 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001261 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 * 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 +02001263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001265{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001266 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001267
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001268 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001269 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001270
1271 /* 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 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001273 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001274 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001276 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001279
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001280 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1282 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001283
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001285 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001287
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001288cleanup:
1289 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001290}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001291
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001292/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001293 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001294 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001295 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 * 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 +01001297 * bring the result back to this range.
1298 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001299 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001300 */
1301
1302/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 * 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 +01001304 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001306#define INC_MUL_COUNT mul_count++;
1307#else
1308#define INC_MUL_COUNT
1309#endif
1310
Hanno Beckerd6028a12018-10-15 12:01:35 +01001311#define MOD_MUL( N ) \
1312 do \
1313 { \
1314 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1315 INC_MUL_COUNT \
1316 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001317
1318/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001320 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001321 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001322#define MOD_SUB( N ) \
1323 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001325
1326/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001327 * 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 +02001328 * We known P, N and the result are positive, so sub_abs is correct, and
1329 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001330 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001331#define MOD_ADD( N ) \
1332 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001334
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001335#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001336/*
1337 * For curves in short Weierstrass form, we do all the internal operations in
1338 * Jacobian coordinates.
1339 *
1340 * For multiplication, we'll use a comb method with coutermeasueres against
1341 * SPA, hence timing attacks.
1342 */
1343
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001344/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001345 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001346 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001348static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001349{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001350 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001354 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001355
Janos Follathb0697532016-08-18 12:38:46 +01001356#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001357 if( mbedtls_internal_ecp_grp_capable( grp ) )
1358 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001359#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001361 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001362
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001363 /*
1364 * X = X / Z^2 mod p
1365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1367 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1368 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 +01001369
1370 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001371 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001373 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1374 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 +01001375
1376 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001377 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001380
1381cleanup:
1382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001384
1385 return( ret );
1386}
1387
1388/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001389 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001390 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001391 * (See for example Cohen's "A Course in Computational Algebraic Number
1392 * Theory", Algorithm 10.3.4.)
1393 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001394 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001395 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001396 *
1397 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001398 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001400 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001401{
1402 int ret;
1403 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001404 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001405
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001406 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001407 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001408
Janos Follathb0697532016-08-18 12:38:46 +01001409#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001410 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001411 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001412#endif
1413
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001414 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001415 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001416
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001417 for( i = 0; i < T_size; i++ )
1418 mbedtls_mpi_init( &c[i] );
1419
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001421
1422 /*
1423 * c[i] = Z_0 * ... * Z_i
1424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001426 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001427 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001428 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001429 MOD_MUL( c[i] );
1430 }
1431
1432 /*
1433 * u = 1 / (Z_0 * ... * Z_n) mod P
1434 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001435 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001436
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001437 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001438 {
1439 /*
1440 * Zi = 1 / Z_i mod p
1441 * u = 1 / (Z_0 * ... * Z_i) mod P
1442 */
1443 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001445 }
1446 else
1447 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1449 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001450 }
1451
1452 /*
1453 * proceed as in normalize()
1454 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1456 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1457 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1458 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 +01001459
1460 /*
1461 * Post-precessing: reclaim some memory by shrinking coordinates
1462 * - not storing Z (always 1)
1463 * - shrinking other coordinates, but still keeping the same number of
1464 * limbs as P, as otherwise it will too likely be regrown too fast.
1465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1467 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1468 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001469
1470 if( i == 0 )
1471 break;
1472 }
1473
1474cleanup:
1475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001476 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001477 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 mbedtls_mpi_free( &c[i] );
1479 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001480
1481 return( ret );
1482}
1483
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001484/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001485 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1486 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1489 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001490 unsigned char inv )
1491{
1492 int ret;
1493 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001497
1498 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1500 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1501 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001502
1503cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001504 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001505
1506 return( ret );
1507}
1508
1509/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001510 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001511 *
Peter Dettmance661b22015-02-07 14:43:51 +07001512 * 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 +01001513 *
Peter Dettmance661b22015-02-07 14:43:51 +07001514 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1515 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1516 *
1517 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1518 *
1519 * Cost: 1D := 3M + 4S (A == 0)
1520 * 4M + 4S (A == -3)
1521 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001522 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001523static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1524 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001525{
1526 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001527 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001529#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001530 dbl_count++;
1531#endif
1532
Janos Follathb0697532016-08-18 12:38:46 +01001533#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001534 if( mbedtls_internal_ecp_grp_capable( grp ) )
1535 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001536#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001537
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001538 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 +01001539
1540 /* Special case for A = -3 */
1541 if( grp->A.p == NULL )
1542 {
Peter Dettmance661b22015-02-07 14:43:51 +07001543 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1546 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1547 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1548 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001549 }
1550 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001551 {
Peter Dettmance661b22015-02-07 14:43:51 +07001552 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001553 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001555
1556 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001557 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001558 {
1559 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001560 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1561 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001564 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001565 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001566
Peter Dettmance661b22015-02-07 14:43:51 +07001567 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001572
Peter Dettmance661b22015-02-07 14:43:51 +07001573 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001574 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1575 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001576
1577 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001578 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001581
1582 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001583 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1584 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1585 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001586
1587 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001588 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1589 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001590
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001591 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1592 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1593 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001594
1595cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001596 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 +02001597
1598 return( ret );
1599}
1600
1601/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001602 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001603 *
1604 * The coordinates of Q must be normalized (= affine),
1605 * but those of P don't need to. R is not normalized.
1606 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001607 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001608 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001609 * - at each step, P, Q and R are multiples of the base point, the factor
1610 * being less than its order, so none of them is zero;
1611 * - Q is an odd multiple of the base point, P an even multiple,
1612 * due to the choice of precomputed points in the modified comb method.
1613 * So branches for these cases do not leak secret information.
1614 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001615 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1616 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001617 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001618 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1620 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001621{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001622 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001623 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001625#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001626 add_count++;
1627#endif
1628
Janos Follathb0697532016-08-18 12:38:46 +01001629#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001630 if( mbedtls_internal_ecp_grp_capable( grp ) )
1631 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001632#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001633
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001634 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001635 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1638 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1641 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001642
1643 /*
1644 * Make sure Q coordinates are normalized
1645 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001646 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1647 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001649 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1650 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001651
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001652 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1655 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1656 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1657 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001658
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001659 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001660 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001661 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001662 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001663 {
1664 ret = ecp_double_jac( grp, R, P );
1665 goto cleanup;
1666 }
1667 else
1668 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001670 goto cleanup;
1671 }
1672 }
1673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1682 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1683 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1684 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1685 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001686
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1688 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001690
1691cleanup:
1692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001693 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1694 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001695
1696 return( ret );
1697}
1698
1699/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001700 * Randomize jacobian coordinates:
1701 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001702 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001703 *
1704 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001705 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001707 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1708{
1709 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001711 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001712 int count = 0;
1713
Janos Follathb0697532016-08-18 12:38:46 +01001714#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001715 if( mbedtls_internal_ecp_grp_capable( grp ) )
1716 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001717#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001718
1719 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001721
1722 /* Generate l such that 1 < l < p */
1723 do
1724 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001725 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1728 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001729
1730 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001731 {
1732 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1733 goto cleanup;
1734 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001735 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001737
1738 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 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 +02001740
1741 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001742 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1743 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 +02001744
1745 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1747 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 +02001748
1749cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001751
1752 return( ret );
1753}
1754
1755/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001756 * Check and define parameters used by the comb method (see below for details)
1757 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1759#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001760#endif
1761
1762/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001763#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001764
1765/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001766#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001767
1768/*
1769 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001770 *
1771 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001772 * modified version that provides resistance to SPA by avoiding zero
1773 * digits in the representation as in [3]. We modify the method further by
1774 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001775 * representation uses one more K_i, due to carries, but saves on the size of
1776 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001777 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001778 * Summary of the comb method and its modifications:
1779 *
1780 * - The goal is to compute m*P for some w*d-bit integer m.
1781 *
1782 * - The basic comb method splits m into the w-bit integers
1783 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1784 * index has residue i modulo d, and computes m * P as
1785 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1786 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1787 *
1788 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1789 * .. + 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]] ..,
1790 * thereby successively converting it into a form where all summands
1791 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1792 *
1793 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1794 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1795 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1796 * Performing and iterating this procedure for those x[i] that are even
1797 * (keeping track of carry), we can transform the original sum into one of the form
1798 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1799 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1800 * which is why we are only computing half of it in the first place in
1801 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1802 *
1803 * - For the sake of compactness, only the seven low-order bits of x[i]
1804 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001805 * 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 +02001806 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001807 *
1808 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001809 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001810 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001811 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001812 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1813 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001814 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001815static void ecp_comb_recode_core( unsigned char x[], size_t d,
1816 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001817{
1818 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001819 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001820
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001821 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001822
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001823 /* First get the classical comb values (except for x_d = 0) */
1824 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001825 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001827
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001828 /* Now make sure x_1 .. x_d are odd */
1829 c = 0;
1830 for( i = 1; i <= d; i++ )
1831 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001832 /* Add carry and update it */
1833 cc = x[i] & c;
1834 x[i] = x[i] ^ c;
1835 c = cc;
1836
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001837 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001838 adjust = 1 - ( x[i] & 0x01 );
1839 c |= x[i] & ( x[i-1] * adjust );
1840 x[i] = x[i] ^ ( x[i-1] * adjust );
1841 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001842 }
1843}
1844
1845/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001846 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001847 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001848 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001849 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001850 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1851 * 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 +01001852 *
1853 * 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 +02001854 *
1855 * Note: Even comb values (those where P would be omitted from the
1856 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001857 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001858 *
1859 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001860 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001861 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1862 * (3) [add] Computation of all T[i]
1863 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001864 *
1865 * Step 1 can be interrupted but not the others; together with the final
1866 * coordinate normalization they are the largest steps done at once, depending
1867 * on the window size. Here are operation counts for P-256:
1868 *
1869 * step (2) (3) (4)
1870 * w = 5 142 165 208
1871 * w = 4 136 77 160
1872 * w = 3 130 33 136
1873 * w = 2 124 11 124
1874 *
1875 * So if ECC operations are blocking for too long even with a low max_ops
1876 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1877 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001878 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001879static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1880 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001881 unsigned char w, size_t d,
1882 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001883{
1884 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001885 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001886 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001887 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001889
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001890#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001891 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001892 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001893 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1894 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001895 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001896 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001897 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1898 goto add;
1899 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1900 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001901 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001902#else
1903 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001904#endif
1905
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001906#if defined(MBEDTLS_ECP_RESTARTABLE)
1907 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1908 {
1909 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1910
1911 /* initial state for the loop */
1912 rs_ctx->rsm->i = 0;
1913 }
1914
1915dbl:
1916#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001917 /*
1918 * Set T[0] = P and
1919 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001921 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001922
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001923#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001924 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1925 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001926 else
1927#endif
1928 j = 0;
1929
1930 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001931 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001932 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001933
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001934 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001935 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001936
1937 if( j % d == 0 )
1938 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1939
1940 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001941 }
1942
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001943#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001944 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1945 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1946
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001947norm_dbl:
1948#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001949 /*
1950 * Normalize current elements in T. As T has holes,
1951 * use an auxiliary array of pointers to elements in T.
1952 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001953 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001954 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001955 TT[j++] = T + i;
1956
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001957 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001958
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001959 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001960
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001961#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001962 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1963 rs_ctx->rsm->state = ecp_rsm_pre_add;
1964
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001965add:
1966#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001967 /*
1968 * Compute the remaining ones using the minimal number of additions
1969 * Be careful to update T[2^l] only after using it!
1970 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001971 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001972
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001973 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001974 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001975 j = i;
1976 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001978 }
1979
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001980#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001981 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1982 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1983
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001984norm_add:
1985#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001986 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02001987 * Normalize final elements in T. Even though there are no holes now, we
1988 * still need the auxiliary array for homogeneity with the previous
1989 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001990 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001991 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001992 TT[j] = T + j + 1;
1993
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001994 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001995
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001996 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001997
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001998cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001999#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002000 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2001 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002002 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002003 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002004 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002005 }
2006#endif
Janos Follathb0697532016-08-18 12:38:46 +01002007
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002008 return( ret );
2009}
2010
2011/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002012 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002013 *
2014 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002017 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002018 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002019{
2020 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002021 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002022
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002023 /* Ignore the "sign" bit and scale down */
2024 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002025
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002026 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002027 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002028 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2030 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002031 }
2032
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002033 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002035
2036cleanup:
2037 return( ret );
2038}
2039
2040/*
2041 * Core multiplication algorithm for the (modified) comb method.
2042 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002043 *
2044 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002047 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002048 const unsigned char x[], size_t d,
2049 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002050 void *p_rng,
2051 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002052{
2053 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002055 size_t i;
2056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002058
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002059#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002060 (void) rs_ctx;
2061#endif
2062
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002063#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002064 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2065 rs_ctx->rsm->state != ecp_rsm_comb_core )
2066 {
2067 rs_ctx->rsm->i = 0;
2068 rs_ctx->rsm->state = ecp_rsm_comb_core;
2069 }
2070
2071 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002072 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002073 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002074 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2075 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002076 }
2077 else
2078#endif
2079 {
2080 /* Start with a non-zero point and randomize its coordinates */
2081 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002082 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002083 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002084#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002085 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002086#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002087 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2088 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002089
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002090 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002091 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002092 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002093 --i;
2094
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002095 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002096 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002098 }
2099
2100cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002102 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002103
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002104#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002105 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2106 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002107 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002108 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002109 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002110 }
2111#endif
2112
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002113 return( ret );
2114}
2115
2116/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002117 * Recode the scalar to get constant-time comb multiplication
2118 *
2119 * As the actual scalar recoding needs an odd scalar as a starting point,
2120 * this wrapper ensures that by replacing m by N - m if necessary, and
2121 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002122 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002123 * This works because we only support large prime order for Short Weierstrass
2124 * curves, so N is always odd hence either m or N - m is.
2125 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002126 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002127 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002128static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2129 const mbedtls_mpi *m,
2130 unsigned char k[COMB_MAX_D + 1],
2131 size_t d,
2132 unsigned char w,
2133 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002134{
2135 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002136 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002137
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002138 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002139 mbedtls_mpi_init( &mm );
2140
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002141 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002142 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2143 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2144
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002145 /* do we need the parity trick? */
2146 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2147
2148 /* execute parity fix in constant time */
2149 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002150 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002151 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2152
2153 /* actual scalar recoding */
2154 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002155
2156cleanup:
2157 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002158 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002159
2160 return( ret );
2161}
2162
2163/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002164 * Perform comb multiplication (for short Weierstrass curves)
2165 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002166 *
2167 * Scalar recoding may use a parity trick that makes us compute -m * P,
2168 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002169 */
2170static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2171 mbedtls_ecp_point *R,
2172 const mbedtls_mpi *m,
2173 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002174 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002175 unsigned char w,
2176 size_t d,
2177 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002178 void *p_rng,
2179 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002180{
2181 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002182 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002183 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002184 mbedtls_ecp_point *RR = R;
2185
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002186#if defined(MBEDTLS_ECP_RESTARTABLE)
2187 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2188 {
2189 RR = &rs_ctx->rsm->R;
2190
2191 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2192 goto final_norm;
2193 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002194#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002195
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002196 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2197 &parity_trick ) );
2198 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2199 f_rng, p_rng, rs_ctx ) );
2200 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2201
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002202#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002203 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002204 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002205
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002206final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002207 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002208#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002209 /*
2210 * Knowledge of the jacobian coordinates may leak the last few bits of the
2211 * scalar [1], and since our MPI implementation isn't constant-flow,
2212 * inversion (used for coordinate normalization) may leak the full value
2213 * of its input via side-channels [2].
2214 *
2215 * [1] https://eprint.iacr.org/2003/191
2216 * [2] https://eprint.iacr.org/2020/055
2217 *
2218 * Avoid the leak by randomizing coordinates before we normalize them.
2219 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002220#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002221 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002222#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002223 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2224
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002225 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2226
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002227#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002228 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2229 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002230#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002231
2232cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002233 return( ret );
2234}
2235
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002236/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002237 * Pick window size based on curve size and whether we optimize for base point
2238 */
2239static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2240 unsigned char p_eq_g )
2241{
2242 unsigned char w;
2243
2244 /*
2245 * Minimize the number of multiplications, that is minimize
2246 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2247 * (see costs of the various parts, with 1S = 1M)
2248 */
2249 w = grp->nbits >= 384 ? 5 : 4;
2250
2251 /*
2252 * If P == G, pre-compute a bit more, since this may be re-used later.
2253 * Just adding one avoids upping the cost of the first mul too much,
2254 * and the memory cost too.
2255 */
2256 if( p_eq_g )
2257 w++;
2258
2259 /*
2260 * Make sure w is within bounds.
2261 * (The last test is useful only for very small curves in the test suite.)
2262 */
2263 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2264 w = MBEDTLS_ECP_WINDOW_SIZE;
2265 if( w >= grp->nbits )
2266 w = 2;
2267
2268 return( w );
2269}
2270
2271/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002272 * Multiplication using the comb method - for curves in short Weierstrass form
2273 *
2274 * This function is mainly responsible for administrative work:
2275 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002276 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002277 * functions): allocation, computation, ownership tranfer, freeing.
2278 *
2279 * It delegates the actual arithmetic work to:
2280 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2281 *
2282 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2285 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002286 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002287 void *p_rng,
2288 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002289{
2290 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002291 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002292 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002293 unsigned char T_size = 0, T_ok = 0;
2294 mbedtls_ecp_point *T = NULL;
2295#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2296 ecp_drbg_context drbg_ctx;
2297
2298 ecp_drbg_init( &drbg_ctx );
2299#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002300
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002301 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002302
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002303#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2304 if( f_rng == NULL )
2305 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002306 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002307 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002308#if defined(MBEDTLS_ECP_RESTARTABLE)
2309 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2310 p_rng = &rs_ctx->rsm->drbg_ctx;
2311 else
2312#endif
2313 p_rng = &drbg_ctx;
2314
2315 /* Initialize internal DRBG if necessary */
2316#if defined(MBEDTLS_ECP_RESTARTABLE)
2317 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2318 rs_ctx->rsm->drbg_seeded == 0 )
2319#endif
2320 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002321 const size_t m_len = ( grp->nbits + 7 ) / 8;
2322 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002323 }
2324#if defined(MBEDTLS_ECP_RESTARTABLE)
2325 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2326 rs_ctx->rsm->drbg_seeded = 1;
2327#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002328 }
2329#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2330
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002331 /* Is P the base point ? */
2332#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2333 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2334 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002335#else
2336 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002337#endif
2338
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002339 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002340 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002341 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002342 d = ( grp->nbits + w - 1 ) / w;
2343
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002344 /* Pre-computed table: do we have it already for the base point? */
2345 if( p_eq_g && grp->T != NULL )
2346 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002347 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002348 T = grp->T;
2349 T_ok = 1;
2350 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002351 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002352#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002353 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002354 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002355 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002356 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002357 T = rs_ctx->rsm->T;
2358 rs_ctx->rsm->T = NULL;
2359 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002360
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002361 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002362 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002363 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002364 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002365#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002366 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002367 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002368 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002369 if( T == NULL )
2370 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002371 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002372 goto cleanup;
2373 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002374
2375 for( i = 0; i < T_size; i++ )
2376 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002377
2378 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002379 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002380
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002381 /* Compute table (or finish computing it) if not done already */
2382 if( !T_ok )
2383 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002384 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002385
2386 if( p_eq_g )
2387 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002388 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002389 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002390 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002391 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002392 }
2393 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002394
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002395 /* Actual comb multiplication using precomputed points */
2396 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002397 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002398 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002399
2400cleanup:
2401
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002402#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2403 ecp_drbg_free( &drbg_ctx );
2404#endif
2405
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002406 /* does T belong to the group? */
2407 if( T == grp->T )
2408 T = NULL;
2409
2410 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002411#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002412 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 +01002413 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002414 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002415 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002416 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002417 T = NULL;
2418 }
2419#endif
2420
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002421 /* did T belong to us? then let's destroy it! */
2422 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002423 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002424 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002425 mbedtls_ecp_point_free( &T[i] );
2426 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002427 }
2428
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002429 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002430#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002431 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2432#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002433 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002434 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002435 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002436
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002437 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002438
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002439 return( ret );
2440}
2441
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002442#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002443
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002444#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002445/*
2446 * For Montgomery curves, we do all the internal arithmetic in projective
2447 * coordinates. Import/export of points uses only the x coordinates, which is
2448 * internaly represented as X / Z.
2449 *
2450 * For scalar multiplication, we'll use a Montgomery ladder.
2451 */
2452
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002453/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002454 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2455 * Cost: 1M + 1I
2456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002457static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002458{
2459 int ret;
2460
Janos Follathb0697532016-08-18 12:38:46 +01002461#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002462 if( mbedtls_internal_ecp_grp_capable( grp ) )
2463 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002464#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2467 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2468 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002469
2470cleanup:
2471 return( ret );
2472}
2473
2474/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002475 * Randomize projective x/z coordinates:
2476 * (X, Z) -> (l X, l Z) for random l
2477 * This is sort of the reverse operation of ecp_normalize_mxz().
2478 *
2479 * This countermeasure was first suggested in [2].
2480 * Cost: 2M
2481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002483 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2484{
2485 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002487 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002488 int count = 0;
2489
Janos Follathb0697532016-08-18 12:38:46 +01002490#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002491 if( mbedtls_internal_ecp_grp_capable( grp ) )
2492 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002493#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002494
2495 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002497
2498 /* Generate l such that 1 < l < p */
2499 do
2500 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2504 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002505
2506 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002507 {
2508 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2509 goto cleanup;
2510 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002511 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2515 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 +01002516
2517cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002518 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002519
2520 return( ret );
2521}
2522
2523/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002524 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2525 * for Montgomery curves in x/z coordinates.
2526 *
2527 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2528 * with
2529 * d = X1
2530 * P = (X2, Z2)
2531 * Q = (X3, Z3)
2532 * R = (X4, Z4)
2533 * S = (X5, Z5)
2534 * and eliminating temporary variables tO, ..., t4.
2535 *
2536 * Cost: 5M + 4S
2537 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2539 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2540 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2541 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002542{
2543 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002545
Janos Follathb0697532016-08-18 12:38:46 +01002546#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002547 if( mbedtls_internal_ecp_grp_capable( grp ) )
2548 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002549#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002550
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2552 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2553 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002555 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2556 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2557 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2559 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2560 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2561 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2562 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2563 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2564 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2566 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2567 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2568 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2569 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2571 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2572 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 +01002573
2574cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002575 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2576 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2577 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002578
2579 return( ret );
2580}
2581
2582/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002583 * Multiplication with Montgomery ladder in x/z coordinates,
2584 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002585 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002586static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2587 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002588 int (*f_rng)(void *, unsigned char *, size_t),
2589 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002590{
2591 int ret;
2592 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002593 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002594 mbedtls_ecp_point RP;
2595 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002596#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2597 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002598
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002599 ecp_drbg_init( &drbg_ctx );
2600#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002602
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002603#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2604 if( f_rng == NULL )
2605 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002606 const size_t m_len = ( grp->nbits + 7 ) / 8;
2607 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002608 f_rng = &ecp_drbg_random;
2609 p_rng = &drbg_ctx;
2610 }
2611#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2612
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002613 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002614 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2615 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002616
2617 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2619 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2620 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002621
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002622 /* RP.X might be sligtly larger than P, so reduce it */
2623 MOD_ADD( RP.X );
2624
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002625 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002626#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002627 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002628#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002630
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002631 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002632 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002633 while( i-- > 0 )
2634 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002636 /*
2637 * if (b) R = 2R + P else R = 2R,
2638 * which is:
2639 * if (b) double_add( RP, R, RP, R )
2640 * else double_add( R, RP, R, RP )
2641 * but using safe conditional swaps to avoid leaks
2642 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2644 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2645 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2646 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2647 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002648 }
2649
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002650 /*
2651 * Knowledge of the projective coordinates may leak the last few bits of the
2652 * scalar [1], and since our MPI implementation isn't constant-flow,
2653 * inversion (used for coordinate normalization) may leak the full value
2654 * of its input via side-channels [2].
2655 *
2656 * [1] https://eprint.iacr.org/2003/191
2657 * [2] https://eprint.iacr.org/2020/055
2658 *
2659 * Avoid the leak by randomizing coordinates before we normalize them.
2660 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002661#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002662 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002663#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002664 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002666 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002667
2668cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002669#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2670 ecp_drbg_free( &drbg_ctx );
2671#endif
2672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002673 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002674
2675 return( ret );
2676}
2677
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002678#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002679
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002680/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002681 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002682 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002683int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002685 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2686 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002687{
Janos Follathb0697532016-08-18 12:38:46 +01002688 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002689#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2690 char is_grp_capable = 0;
2691#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002692 ECP_VALIDATE_RET( grp != NULL );
2693 ECP_VALIDATE_RET( R != NULL );
2694 ECP_VALIDATE_RET( m != NULL );
2695 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002696
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002697#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002698 /* reset ops count for this call if top-level */
2699 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2700 rs_ctx->ops_done = 0;
2701#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002702
Janos Follathc44ab972016-11-18 16:38:23 +00002703#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002704 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002705 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002706#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002707
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002708#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002709 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002710 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002711#endif
2712 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002713 /* check_privkey is free */
2714 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2715
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002716 /* Common sanity checks */
2717 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2718 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002719 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002720
2721 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002722#if defined(ECP_MONTGOMERY)
2723 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002724 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002725#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002726#if defined(ECP_SHORTWEIERSTRASS)
2727 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002728 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002729#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002730
Janos Follath6c8ccd52016-11-29 15:37:09 +00002731cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002732
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002733#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002734 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002735 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002736#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002737
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002738#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002739 if( rs_ctx != NULL )
2740 rs_ctx->depth--;
2741#endif
2742
Janos Follathb0697532016-08-18 12:38:46 +01002743 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002744}
2745
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002746/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002747 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002748 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002749int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002750 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002751 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002752{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002753 ECP_VALIDATE_RET( grp != NULL );
2754 ECP_VALIDATE_RET( R != NULL );
2755 ECP_VALIDATE_RET( m != NULL );
2756 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002757 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002758}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002759
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002760#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002761/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002762 * Check that an affine point is valid as a public key,
2763 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002764 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002765static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002766{
2767 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002768 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002769
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002770 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002771 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2772 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2773 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2774 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2775 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002777 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002778
2779 /*
2780 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002781 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2784 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002785
2786 /* Special case for A = -3 */
2787 if( grp->A.p == NULL )
2788 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002790 }
2791 else
2792 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002793 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002794 }
2795
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002796 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2797 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002799 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2800 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002801
2802cleanup:
2803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002804 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002805
2806 return( ret );
2807}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002808#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002809
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002810/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002811 * R = m * P with shortcuts for m == 1 and m == -1
2812 * NOT constant-time - ONLY for short Weierstrass!
2813 */
2814static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2815 mbedtls_ecp_point *R,
2816 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002817 const mbedtls_ecp_point *P,
2818 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002819{
2820 int ret;
2821
2822 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2823 {
2824 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2825 }
2826 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2827 {
2828 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2829 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2830 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2831 }
2832 else
2833 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002834 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2835 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002836 }
2837
2838cleanup:
2839 return( ret );
2840}
2841
2842/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002843 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002844 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002845 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002846int mbedtls_ecp_muladd_restartable(
2847 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002848 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002849 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2850 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002851{
2852 int ret;
2853 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002854 mbedtls_ecp_point *pmP = &mP;
2855 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002856#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2857 char is_grp_capable = 0;
2858#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002859 ECP_VALIDATE_RET( grp != NULL );
2860 ECP_VALIDATE_RET( R != NULL );
2861 ECP_VALIDATE_RET( m != NULL );
2862 ECP_VALIDATE_RET( P != NULL );
2863 ECP_VALIDATE_RET( n != NULL );
2864 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002865
2866 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2867 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2868
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002869 mbedtls_ecp_point_init( &mP );
2870
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002871 ECP_RS_ENTER( ma );
2872
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002873#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002874 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2875 {
2876 /* redirect intermediate results to restart context */
2877 pmP = &rs_ctx->ma->mP;
2878 pR = &rs_ctx->ma->R;
2879
2880 /* jump to next operation */
2881 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2882 goto mul2;
2883 if( rs_ctx->ma->state == ecp_rsma_add )
2884 goto add;
2885 if( rs_ctx->ma->state == ecp_rsma_norm )
2886 goto norm;
2887 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002888#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002889
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002890 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002891#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002892 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002893 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002894
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002895mul2:
2896#endif
2897 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002898
2899#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2900 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2901 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2902#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2903
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002904#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002905 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002906 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002907
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002908add:
2909#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002910 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002911 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
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 )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002914 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002915
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002916norm:
2917#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002918 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002919 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2920
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002921#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002922 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2923 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2924#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002925
2926cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002927#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002928 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002929 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002930#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002931
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002932 mbedtls_ecp_point_free( &mP );
2933
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002934 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002935
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002936 return( ret );
2937}
2938
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002939/*
2940 * Linear combination
2941 * NOT constant-time
2942 */
2943int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2944 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2945 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2946{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002947 ECP_VALIDATE_RET( grp != NULL );
2948 ECP_VALIDATE_RET( R != NULL );
2949 ECP_VALIDATE_RET( m != NULL );
2950 ECP_VALIDATE_RET( P != NULL );
2951 ECP_VALIDATE_RET( n != NULL );
2952 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002953 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2954}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002955
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002956#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002957/*
2958 * Check validity of a public key for Montgomery curves with x-only schemes
2959 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002960static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002961{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002962 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002963 /* Allow any public value, if it's too big then we'll just reduce it mod p
2964 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002965 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2966 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002967
2968 return( 0 );
2969}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002970#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002971
2972/*
2973 * Check that a point is valid as a public key
2974 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002975int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2976 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002977{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002978 ECP_VALIDATE_RET( grp != NULL );
2979 ECP_VALIDATE_RET( pt != NULL );
2980
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002981 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002982 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2983 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002984
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002985#if defined(ECP_MONTGOMERY)
2986 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002987 return( ecp_check_pubkey_mx( grp, pt ) );
2988#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002989#if defined(ECP_SHORTWEIERSTRASS)
2990 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002991 return( ecp_check_pubkey_sw( grp, pt ) );
2992#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002993 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002994}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002995
2996/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002997 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002998 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002999int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
3000 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003001{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003002 ECP_VALIDATE_RET( grp != NULL );
3003 ECP_VALIDATE_RET( d != NULL );
3004
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003005#if defined(ECP_MONTGOMERY)
3006 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003007 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003008 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003009 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
3010 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003011 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003012 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003013
3014 /* see [Curve25519] page 5 */
3015 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3016 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3017
3018 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003019 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003020#endif /* ECP_MONTGOMERY */
3021#if defined(ECP_SHORTWEIERSTRASS)
3022 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003023 {
3024 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003025 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3026 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3027 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003028 else
3029 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003030 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003031#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003032
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003033 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003034}
3035
3036/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003037 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003038 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003039int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3040 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003041 int (*f_rng)(void *, unsigned char *, size_t),
3042 void *p_rng )
3043{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003044 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003045 size_t n_size;
3046
3047 ECP_VALIDATE_RET( grp != NULL );
3048 ECP_VALIDATE_RET( d != NULL );
3049 ECP_VALIDATE_RET( f_rng != NULL );
3050
3051 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003052
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003053#if defined(ECP_MONTGOMERY)
3054 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003055 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003056 /* [M225] page 5 */
3057 size_t b;
3058
Janos Follath98e28a72016-05-31 14:03:54 +01003059 do {
3060 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3061 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003062
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003063 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003064 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003065 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003066 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003067 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003068 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003069
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003070 /* Make sure the last two bits are unset for Curve448, three bits for
3071 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003072 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3073 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003074 if( grp->nbits == 254 )
3075 {
3076 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3077 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003078 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003079#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003080
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003081#if defined(ECP_SHORTWEIERSTRASS)
3082 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003083 {
3084 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003085 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003086 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003087
3088 /*
3089 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3090 * - use the same byte ordering;
3091 * - keep the leftmost nbits bits of the generated octet string;
3092 * - try until result is in the desired range.
3093 * This also avoids any biais, which is especially important for ECDSA.
3094 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003095 do
3096 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003097 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003098 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003099
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003100 /*
3101 * Each try has at worst a probability 1/2 of failing (the msb has
3102 * a probability 1/2 of being 0, and then the result will be < N),
3103 * so after 30 tries failure probability is a most 2**(-30).
3104 *
3105 * For most curves, 1 try is enough with overwhelming probability,
3106 * since N starts with a lot of 1s in binary, but some curves
3107 * such as secp224k1 are actually very close to the worst case.
3108 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003109 if( ++count > 30 )
3110 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003111
Janos Follath867a3ab2019-10-11 14:21:53 +01003112 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003113 if( ret != 0 )
3114 {
3115 goto cleanup;
3116 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003117 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003118 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003119 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003120#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003121
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003122cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003123 return( ret );
3124}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003125
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003126/*
3127 * Generate a keypair with configurable base point
3128 */
3129int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3130 const mbedtls_ecp_point *G,
3131 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3132 int (*f_rng)(void *, unsigned char *, size_t),
3133 void *p_rng )
3134{
3135 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003136 ECP_VALIDATE_RET( grp != NULL );
3137 ECP_VALIDATE_RET( d != NULL );
3138 ECP_VALIDATE_RET( G != NULL );
3139 ECP_VALIDATE_RET( Q != NULL );
3140 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003141
3142 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3143 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3144
3145cleanup:
3146 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003147}
3148
3149/*
3150 * Generate key pair, wrapper for conventional base point
3151 */
3152int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3153 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3154 int (*f_rng)(void *, unsigned char *, size_t),
3155 void *p_rng )
3156{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003157 ECP_VALIDATE_RET( grp != NULL );
3158 ECP_VALIDATE_RET( d != NULL );
3159 ECP_VALIDATE_RET( Q != NULL );
3160 ECP_VALIDATE_RET( f_rng != NULL );
3161
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003162 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003163}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003164
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003165/*
3166 * Generate a keypair, prettier wrapper
3167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003168int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003169 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3170{
3171 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003172 ECP_VALIDATE_RET( key != NULL );
3173 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003174
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003175 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003176 return( ret );
3177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003179}
3180
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003181/*
3182 * Check a public-private key pair
3183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003184int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003185{
3186 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003187 mbedtls_ecp_point Q;
3188 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003189 ECP_VALIDATE_RET( pub != NULL );
3190 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003191
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003192 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003193 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003194 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3195 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3196 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003197 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003198 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003199 }
3200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003201 mbedtls_ecp_point_init( &Q );
3202 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003204 /* mbedtls_ecp_mul() needs a non-const group... */
3205 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003206
3207 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003208 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3211 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3212 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003213 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003214 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003215 goto cleanup;
3216 }
3217
3218cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003219 mbedtls_ecp_point_free( &Q );
3220 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003221
3222 return( ret );
3223}
3224
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003225#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003226
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003227#if defined(ECP_ONE_STEP_KDF)
3228/*
3229 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3230 * but unofficial ones can be found at:
3231 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3232 *
3233 * We only use the ones with empty fixedInfo, and for brevity's sake, only
3234 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
3235 * exactly one block, and with SHA-512 less than one block).
3236 */
3237#if defined(MBEDTLS_SHA512_C)
3238
3239static const uint8_t test_kdf_z[16] = {
3240 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
3241 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
3242};
3243static const uint8_t test_kdf_out[32] = {
3244 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
3245 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
3246 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
3247 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
3248};
3249
3250#elif defined(MBEDTLS_SHA256_C)
3251
3252static const uint8_t test_kdf_z[16] = {
3253 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
3254 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
3255};
3256static const uint8_t test_kdf_out[32] = {
3257 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
3258 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
3259 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
3260 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
3261};
3262
3263#elif defined(MBEDTLS_SHA1_C)
3264
3265static const uint8_t test_kdf_z[16] = {
3266 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
3267 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
3268};
3269static const uint8_t test_kdf_out[32] = {
3270 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
3271 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
3272 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
3273 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
3274};
3275
3276#else
3277#error "Need at least one of SHA-512, SHA-256 or SHA-1"
3278#endif
3279
3280static int ecp_kdf_self_test( void )
3281{
3282 int ret;
3283 ecp_drbg_context kdf_ctx;
3284 mbedtls_mpi scalar;
3285 uint8_t out[sizeof( test_kdf_out )];
3286
3287 ecp_drbg_init( &kdf_ctx );
3288 mbedtls_mpi_init( &scalar );
3289 memset( out, 0, sizeof( out ) );
3290
3291 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3292 test_kdf_z, sizeof( test_kdf_z ) ) );
3293
3294 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3295 &scalar, sizeof( test_kdf_z ) ) );
3296
3297 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3298
3299 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3300 ret = -1;
3301
3302cleanup:
3303 ecp_drbg_free( &kdf_ctx );
3304 mbedtls_mpi_free( &scalar );
3305
3306 return( ret );
3307}
3308#endif /* ECP_ONE_STEP_KDF */
3309
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003310/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003311 * Checkup routine
3312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003313int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003314{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003315 int ret;
3316 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003317 mbedtls_ecp_group grp;
3318 mbedtls_ecp_point R, P;
3319 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003320 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003321 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003322 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003323 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003324 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003325 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003326 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003327 "400000000000000000000000000000000000000000000000", /* one and zeros */
3328 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3329 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003330 };
3331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003332 mbedtls_ecp_group_init( &grp );
3333 mbedtls_ecp_point_init( &R );
3334 mbedtls_ecp_point_init( &P );
3335 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003336
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003337 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003338#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003339 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003340#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003341 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003342#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003343
3344 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003345 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003346
3347 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003348 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3349 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003350
3351 add_count = 0;
3352 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003353 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003354 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3355 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003356
3357 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3358 {
3359 add_c_prev = add_count;
3360 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003361 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003362 add_count = 0;
3363 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003364 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003366 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3367 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003368
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003369 if( add_count != add_c_prev ||
3370 dbl_count != dbl_c_prev ||
3371 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003372 {
3373 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003374 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003375
3376 ret = 1;
3377 goto cleanup;
3378 }
3379 }
3380
3381 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003382 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003383
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003384 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003385 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003386 /* We computed P = 2G last time, use it */
3387
3388 add_count = 0;
3389 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003390 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003391 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3392 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003393
3394 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3395 {
3396 add_c_prev = add_count;
3397 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003398 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003399 add_count = 0;
3400 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003401 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003402
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003403 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3404 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003405
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003406 if( add_count != add_c_prev ||
3407 dbl_count != dbl_c_prev ||
3408 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003409 {
3410 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003411 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003412
3413 ret = 1;
3414 goto cleanup;
3415 }
3416 }
3417
3418 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003419 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003420
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003421#if defined(ECP_ONE_STEP_KDF)
3422 if( verbose != 0 )
3423 mbedtls_printf( " ECP test #3 (internal KDF): " );
3424
3425 ret = ecp_kdf_self_test();
3426 if( ret != 0 )
3427 {
3428 if( verbose != 0 )
3429 mbedtls_printf( "failed\n" );
3430
3431 ret = 1;
3432 goto cleanup;
3433 }
3434
3435 if( verbose != 0 )
3436 mbedtls_printf( "passed\n" );
3437#endif /* ECP_ONE_STEP_KDF */
3438
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003439cleanup:
3440
3441 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003442 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003443
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003444 mbedtls_ecp_group_free( &grp );
3445 mbedtls_ecp_point_free( &R );
3446 mbedtls_ecp_point_free( &P );
3447 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003448
3449 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003450 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003451
3452 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003453}
3454
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003455#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003456
Janos Follathb0697532016-08-18 12:38:46 +01003457#endif /* !MBEDTLS_ECP_ALT */
3458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003459#endif /* MBEDTLS_ECP_C */