blob: b8ad9357a88e5430724e520d970730e7d2b50deb [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{
183 const unsigned char *secret_p = (const unsigned char *) secret->p;
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200184
185 /* 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é-Gonnard72177e32020-06-16 12:51:42 +0200189 return( mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_p, secret_len ) );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200190}
191
192#elif defined(MBEDTLS_CTR_DRBG_C)
193
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200194/* DRBG context type */
195typedef mbedtls_ctr_drbg_context ecp_drbg_context;
196
197/* DRBG context init */
198static inline void ecp_drbg_init( ecp_drbg_context *ctx )
199{
200 mbedtls_ctr_drbg_init( ctx );
201}
202
203/* DRBG context free */
204static inline void ecp_drbg_free( ecp_drbg_context *ctx )
205{
206 mbedtls_ctr_drbg_free( ctx );
207}
208
209/* DRBG function */
210static inline int ecp_drbg_random( void *p_rng,
211 unsigned char *output, size_t output_len )
212{
213 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
214}
215
216/*
217 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
218 * we need to pass an entropy function when seeding. So we use a dummy
219 * function for that, and pass the actual entropy as customisation string.
220 * (During seeding of CTR_DRBG the entropy input and customisation string are
221 * concatenated before being used to update the secret state.)
222 */
223static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
224{
225 (void) ctx;
226 memset( out, 0, len );
227 return( 0 );
228}
229
230/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200231static int ecp_drbg_seed( ecp_drbg_context *ctx,
232 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200233{
234 const unsigned char *secret_p = (const unsigned char *) secret->p;
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200235
236 return( mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200237 secret_p, secret_len ) );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200238}
239
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200240#elif defined(MBEDTLS_SHA512_C) || \
241 defined(MBEDTLS_SHA256_C) || \
242 defined(MBEDTLS_SHA1_C)
243
244/* This will be used in the self-test function */
245#define ECP_ONE_STEP_KDF
246
247/*
248 * We need to expand secret data (the scalar) into a longer stream of bytes.
249 *
250 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
251 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
252 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
253 *
254 * We need a basic hash abstraction layer to use whatever SHA is available.
255 */
256#if defined(MBEDTLS_SHA512_C)
257
258#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
259#define HASH_BLOCK_BYTES ( 512 / 8 )
260
261#elif defined(MBEDTLS_SHA256_C)
262
263#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
264#define HASH_BLOCK_BYTES ( 256 / 8 )
265
266#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
267
268#define HASH_FUNC mbedtls_sha1_ret
269#define HASH_BLOCK_BYTES ( 160 / 8 )
270
271#endif /* SHA512/SHA256/SHA1 abstraction */
272
273/*
274 * State consists of a 32-bit counter plus the secret value.
275 *
276 * We stored them concatenated in a single buffer as that's what will get
277 * passed to the hash function.
278 */
279typedef struct {
280 size_t total_len;
281 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
282} ecp_drbg_context;
283
284static void ecp_drbg_init( ecp_drbg_context *ctx )
285{
286 memset( ctx, 0, sizeof( ecp_drbg_context ) );
287}
288
289static void ecp_drbg_free( ecp_drbg_context *ctx )
290{
291 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
292}
293
294static int ecp_drbg_seed( ecp_drbg_context *ctx,
295 const mbedtls_mpi *secret, size_t secret_len )
296{
297 ctx->total_len = 4 + secret_len;
298 memset( ctx->buf, 0, 4);
299 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
300}
301
302static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
303{
304 ecp_drbg_context *ctx = p_rng;
305 int ret;
306 size_t len_done = 0;
307
308 while( len_done < output_len )
309 {
310 uint8_t tmp[HASH_BLOCK_BYTES];
311 uint8_t use_len;
312
313 /* We don't need to draw more that 255 blocks, so don't bother with
314 * carry propagation and just return an error instead. */
315 ctx->buf[3] += 1;
316 if( ctx->buf[3] == 0 )
317 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
318
319 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
320 if( ret != 0 )
321 return( ret );
322
323 if( output_len - len_done > HASH_BLOCK_BYTES )
324 use_len = HASH_BLOCK_BYTES;
325 else
326 use_len = output_len - len_done;
327
328 memcpy( output + len_done, tmp, use_len );
329 len_done += use_len;
330 }
331
332 return( 0 );
333}
334
335#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200336#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200337#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200338#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
339
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200340#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100341/*
342 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200343 *
344 * Default value 0 means that ECC operations will not yield.
345 * Note that regardless of the value of ecp_max_ops, always at
346 * least one step is performed before yielding.
347 *
348 * Setting ecp_max_ops=1 can be suitable for testing purposes
349 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100350 */
351static unsigned ecp_max_ops = 0;
352
353/*
354 * Set ecp_max_ops
355 */
356void mbedtls_ecp_set_max_ops( unsigned max_ops )
357{
358 ecp_max_ops = max_ops;
359}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100360
361/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200362 * Check if restart is enabled
363 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200364int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200365{
366 return( ecp_max_ops != 0 );
367}
368
369/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200370 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100371 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200372struct mbedtls_ecp_restart_mul
373{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100374 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100375 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100376 mbedtls_ecp_point *T; /* table for precomputed points */
377 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200378 enum { /* what were we doing last time we returned? */
379 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
380 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100381 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
382 ecp_rsm_pre_add, /* precompute remaining points by adding */
383 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200384 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100385 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100386 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200387#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
388 ecp_drbg_context drbg_ctx;
389 unsigned char drbg_seeded;
390#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100391};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100392
393/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200394 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100395 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200396static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100397{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200398 mbedtls_ecp_point_init( &ctx->R );
399 ctx->i = 0;
400 ctx->T = NULL;
401 ctx->T_size = 0;
402 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200403#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
404 ecp_drbg_init( &ctx->drbg_ctx );
405 ctx->drbg_seeded = 0;
406#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100407}
408
409/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200410 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100411 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200412static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100413{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100414 unsigned char i;
415
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100416 if( ctx == NULL )
417 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100418
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100419 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100420
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200421 if( ctx->T != NULL )
422 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100423 for( i = 0; i < ctx->T_size; i++ )
424 mbedtls_ecp_point_free( ctx->T + i );
425 mbedtls_free( ctx->T );
426 }
427
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200428#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
429 ecp_drbg_free( &ctx->drbg_ctx );
430#endif
431
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200432 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100433}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100434
435/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200436 * Restart context for ecp_muladd()
437 */
438struct mbedtls_ecp_restart_muladd
439{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200440 mbedtls_ecp_point mP; /* mP value */
441 mbedtls_ecp_point R; /* R intermediate result */
442 enum { /* what should we do next? */
443 ecp_rsma_mul1 = 0, /* first multiplication */
444 ecp_rsma_mul2, /* second multiplication */
445 ecp_rsma_add, /* addition */
446 ecp_rsma_norm, /* normalization */
447 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200448};
449
450/*
451 * Init restart_muladd sub-context
452 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200453static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200454{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200455 mbedtls_ecp_point_init( &ctx->mP );
456 mbedtls_ecp_point_init( &ctx->R );
457 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200458}
459
460/*
461 * Free the components of a restart_muladd sub-context
462 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200463static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200464{
465 if( ctx == NULL )
466 return;
467
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200468 mbedtls_ecp_point_free( &ctx->mP );
469 mbedtls_ecp_point_free( &ctx->R );
470
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200471 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200472}
473
474/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200475 * Initialize a restart context
476 */
477void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
478{
Hanno Becker80f71682018-12-18 23:44:43 +0000479 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200480 ctx->ops_done = 0;
481 ctx->depth = 0;
482 ctx->rsm = NULL;
483 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200484}
485
486/*
487 * Free the components of a restart context
488 */
489void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
490{
491 if( ctx == NULL )
492 return;
493
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200494 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200495 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200496
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200497 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200498 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200499
500 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200501}
502
503/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100504 * Check if we can do the next step
505 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200506int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
507 mbedtls_ecp_restart_ctx *rs_ctx,
508 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100509{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000510 ECP_VALIDATE_RET( grp != NULL );
511
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200512 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100513 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100514 /* scale depending on curve size: the chosen reference is 256-bit,
515 * and multiplication is quadratic. Round to the closest integer. */
516 if( grp->pbits >= 512 )
517 ops *= 4;
518 else if( grp->pbits >= 384 )
519 ops *= 2;
520
Hanno Beckerb10c6602018-10-26 13:50:13 +0100521 /* Avoid infinite loops: always allow first step.
522 * Because of that, however, it's not generally true
523 * that ops_done <= ecp_max_ops, so the check
524 * ops_done > ecp_max_ops below is mandatory. */
525 if( ( rs_ctx->ops_done != 0 ) &&
526 ( rs_ctx->ops_done > ecp_max_ops ||
527 ops > ecp_max_ops - rs_ctx->ops_done ) )
528 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100529 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100530 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100531
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100532 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200533 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100534 }
535
536 return( 0 );
537}
538
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200539/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200540#define ECP_RS_ENTER( SUB ) do { \
541 /* reset ops count for this call if top-level */ \
542 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
543 rs_ctx->ops_done = 0; \
544 \
545 /* set up our own sub-context if needed */ \
546 if( mbedtls_ecp_restart_is_enabled() && \
547 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
548 { \
549 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
550 if( rs_ctx->SUB == NULL ) \
551 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
552 \
553 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
554 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200555} while( 0 )
556
557/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200558#define ECP_RS_LEAVE( SUB ) do { \
559 /* clear our sub-context when not in progress (done or error) */ \
560 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
561 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
562 { \
563 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
564 mbedtls_free( rs_ctx->SUB ); \
565 rs_ctx->SUB = NULL; \
566 } \
567 \
568 if( rs_ctx != NULL ) \
569 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200570} while( 0 )
571
572#else /* MBEDTLS_ECP_RESTARTABLE */
573
574#define ECP_RS_ENTER( sub ) (void) rs_ctx;
575#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
576
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200577#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
580 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
581 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
582 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
583 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
584 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
585 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
586 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
587 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
588 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
589 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200590#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100591#endif
592
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000593#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
594 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200595#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100596#endif
597
598/*
599 * Curve types: internal for now, might be exposed later
600 */
601typedef enum
602{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200603 ECP_TYPE_NONE = 0,
604 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
605 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100606} ecp_curve_type;
607
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100608/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200609 * List of supported curves:
610 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200611 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200612 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200613 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100614 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100615 * Curves are listed in order: largest curves first, and for a given size,
616 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200617 *
618 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200621{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
623 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200624#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
626 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100627#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
629 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200630#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
632 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100633#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
635 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200636#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
638 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100639#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
641 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100642#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
644 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200645#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
647 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100648#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
650 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100651#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
653 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100654#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200656};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100657
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200658#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
659 sizeof( ecp_supported_curves[0] )
660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200662
663/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200664 * List of supported curves and associated info
665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200667{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200668 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200669}
670
671/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100672 * List of supported curves, group ID only
673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100675{
676 static int init_done = 0;
677
678 if( ! init_done )
679 {
680 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 for( curve_info = mbedtls_ecp_curve_list();
684 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100685 curve_info++ )
686 {
687 ecp_supported_grp_id[i++] = curve_info->grp_id;
688 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100690
691 init_done = 1;
692 }
693
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200694 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100695}
696
697/*
698 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200699 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700const 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 +0200701{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 for( curve_info = mbedtls_ecp_curve_list();
705 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200706 curve_info++ )
707 {
708 if( curve_info->grp_id == grp_id )
709 return( curve_info );
710 }
711
712 return( NULL );
713}
714
715/*
716 * Get the curve info from the TLS identifier
717 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200719{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 for( curve_info = mbedtls_ecp_curve_list();
723 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200724 curve_info++ )
725 {
726 if( curve_info->tls_id == tls_id )
727 return( curve_info );
728 }
729
730 return( NULL );
731}
732
733/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100734 * Get the curve info from the name
735 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100737{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100739
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000740 if( name == NULL )
741 return( NULL );
742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 for( curve_info = mbedtls_ecp_curve_list();
744 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100745 curve_info++ )
746 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200747 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100748 return( curve_info );
749 }
750
751 return( NULL );
752}
753
754/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100755 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100756 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100758{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100759 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200760 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100761
762 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200763 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100764 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200765 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100766}
767
768/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100769 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100770 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100772{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000773 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100774
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 mbedtls_mpi_init( &pt->X );
776 mbedtls_mpi_init( &pt->Y );
777 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100778}
779
780/*
781 * Initialize (the components of) a group
782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100784{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000785 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100786
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200787 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200788 mbedtls_mpi_init( &grp->P );
789 mbedtls_mpi_init( &grp->A );
790 mbedtls_mpi_init( &grp->B );
791 mbedtls_ecp_point_init( &grp->G );
792 mbedtls_mpi_init( &grp->N );
793 grp->pbits = 0;
794 grp->nbits = 0;
795 grp->h = 0;
796 grp->modp = NULL;
797 grp->t_pre = NULL;
798 grp->t_post = NULL;
799 grp->t_data = NULL;
800 grp->T = NULL;
801 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100802}
803
804/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200805 * Initialize (the components of) a key pair
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200808{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000809 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811 mbedtls_ecp_group_init( &key->grp );
812 mbedtls_mpi_init( &key->d );
813 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200814}
815
816/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100817 * Unallocate (the components of) a point
818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100820{
821 if( pt == NULL )
822 return;
823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200824 mbedtls_mpi_free( &( pt->X ) );
825 mbedtls_mpi_free( &( pt->Y ) );
826 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100827}
828
829/*
830 * Unallocate (the components of) a group
831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100833{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200834 size_t i;
835
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100836 if( grp == NULL )
837 return;
838
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100839 if( grp->h != 1 )
840 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841 mbedtls_mpi_free( &grp->P );
842 mbedtls_mpi_free( &grp->A );
843 mbedtls_mpi_free( &grp->B );
844 mbedtls_ecp_point_free( &grp->G );
845 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100846 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200847
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200848 if( grp->T != NULL )
849 {
850 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 mbedtls_ecp_point_free( &grp->T[i] );
852 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200853 }
854
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500855 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100856}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100857
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100858/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200859 * Unallocate (the components of) a key pair
860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200862{
Paul Bakker66d5d072014-06-17 16:39:18 +0200863 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200864 return;
865
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866 mbedtls_ecp_group_free( &key->grp );
867 mbedtls_mpi_free( &key->d );
868 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200869}
870
871/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200872 * Copy the contents of a point
873 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200875{
876 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000877 ECP_VALIDATE_RET( P != NULL );
878 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
881 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
882 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200883
884cleanup:
885 return( ret );
886}
887
888/*
889 * Copy the contents of a group object
890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200891int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200892{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000893 ECP_VALIDATE_RET( dst != NULL );
894 ECP_VALIDATE_RET( src != NULL );
895
896 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200897}
898
899/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100900 * Set point to zero
901 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100903{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100904 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000905 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100906
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
908 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
909 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100910
911cleanup:
912 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100913}
914
915/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100916 * Tell if a point is zero
917 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100919{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000920 ECP_VALIDATE_RET( pt != NULL );
921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100923}
924
925/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700926 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200927 */
928int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
929 const mbedtls_ecp_point *Q )
930{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000931 ECP_VALIDATE_RET( P != NULL );
932 ECP_VALIDATE_RET( Q != NULL );
933
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200934 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
935 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
936 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
937 {
938 return( 0 );
939 }
940
941 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
942}
943
944/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100945 * Import a non-zero point from ASCII strings
946 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100948 const char *x, const char *y )
949{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100950 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000951 ECP_VALIDATE_RET( P != NULL );
952 ECP_VALIDATE_RET( x != NULL );
953 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
956 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
957 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100958
959cleanup:
960 return( ret );
961}
962
963/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100964 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100965 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000966int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
967 const mbedtls_ecp_point *P,
968 int format, size_t *olen,
969 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100970{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200971 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100972 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000973 ECP_VALIDATE_RET( grp != NULL );
974 ECP_VALIDATE_RET( P != NULL );
975 ECP_VALIDATE_RET( olen != NULL );
976 ECP_VALIDATE_RET( buf != NULL );
977 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
978 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100979
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100980 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100981 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100982 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100984 {
985 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200986 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100987
988 buf[0] = 0x00;
989 *olen = 1;
990
991 return( 0 );
992 }
993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100995
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200996 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100997 {
998 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100999
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001000 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001002
1003 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1005 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001006 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001008 {
1009 *olen = plen + 1;
1010
1011 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001013
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1015 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001016 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001017
1018cleanup:
1019 return( ret );
1020}
1021
1022/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001023 * Import a point from unsigned binary data (SEC1 2.3.4)
1024 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001025int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1026 mbedtls_ecp_point *pt,
1027 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001028{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001029 int ret;
1030 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001031 ECP_VALIDATE_RET( grp != NULL );
1032 ECP_VALIDATE_RET( pt != NULL );
1033 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001034
Paul Bakker82788fb2014-10-20 13:59:19 +02001035 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001037
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001038 if( buf[0] == 0x00 )
1039 {
1040 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001042 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001044 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001047
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001048 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001050
1051 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1055 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1056 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001057
1058cleanup:
1059 return( ret );
1060}
1061
1062/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001063 * Import a point from a TLS ECPoint record (RFC 4492)
1064 * struct {
1065 * opaque point <1..2^8-1>;
1066 * } ECPoint;
1067 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001068int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1069 mbedtls_ecp_point *pt,
1070 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001071{
1072 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001073 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001074 ECP_VALIDATE_RET( grp != NULL );
1075 ECP_VALIDATE_RET( pt != NULL );
1076 ECP_VALIDATE_RET( buf != NULL );
1077 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001078
1079 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001080 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001081 */
1082 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001084
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001085 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001086 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001088
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001089 /*
1090 * Save buffer start for read_binary and update buf
1091 */
1092 buf_start = *buf;
1093 *buf += data_len;
1094
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001095 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001096}
1097
1098/*
1099 * Export a point as a TLS ECPoint record (RFC 4492)
1100 * struct {
1101 * opaque point <1..2^8-1>;
1102 * } ECPoint;
1103 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001104int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001105 int format, size_t *olen,
1106 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001107{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001108 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001109 ECP_VALIDATE_RET( grp != NULL );
1110 ECP_VALIDATE_RET( pt != NULL );
1111 ECP_VALIDATE_RET( olen != NULL );
1112 ECP_VALIDATE_RET( buf != NULL );
1113 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1114 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001115
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001116 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001117 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001118 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001119 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001120 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001122 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001123 olen, buf + 1, blen - 1) ) != 0 )
1124 return( ret );
1125
1126 /*
1127 * write length to the first byte and update total length
1128 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001129 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001130 ++*olen;
1131
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001132 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001133}
1134
1135/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001136 * Set a group from an ECParameters record (RFC 4492)
1137 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001138int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1139 const unsigned char **buf, size_t len )
1140{
1141 int ret;
1142 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001143 ECP_VALIDATE_RET( grp != NULL );
1144 ECP_VALIDATE_RET( buf != NULL );
1145 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001146
1147 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1148 return( ret );
1149
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001150 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001151}
1152
1153/*
1154 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1155 * mbedtls_ecp_group_id.
1156 */
1157int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1158 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001159{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001160 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001161 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001162 ECP_VALIDATE_RET( grp != NULL );
1163 ECP_VALIDATE_RET( buf != NULL );
1164 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001165
1166 /*
1167 * We expect at least three bytes (see below)
1168 */
1169 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001171
1172 /*
1173 * First byte is curve_type; only named_curve is handled
1174 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1176 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001177
1178 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001179 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001180 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001181 tls_id = *(*buf)++;
1182 tls_id <<= 8;
1183 tls_id |= *(*buf)++;
1184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1186 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001187
Janos Follath89ac8c92018-10-30 11:24:05 +00001188 *grp = curve_info->grp_id;
1189
1190 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001191}
1192
1193/*
1194 * Write the ECParameters record corresponding to a group (RFC 4492)
1195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001196int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001197 unsigned char *buf, size_t blen )
1198{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001199 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001200 ECP_VALIDATE_RET( grp != NULL );
1201 ECP_VALIDATE_RET( buf != NULL );
1202 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001204 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1205 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001206
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001207 /*
1208 * We are going to write 3 bytes (see below)
1209 */
1210 *olen = 3;
1211 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001212 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001213
1214 /*
1215 * First byte is curve_type, always named_curve
1216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001218
1219 /*
1220 * Next two bytes are the namedcurve value
1221 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001222 buf[0] = curve_info->tls_id >> 8;
1223 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001224
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001225 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001226}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001227
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001228/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1230 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001231 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 * 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 +02001233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001234static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001235{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001236 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001237
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001238 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001239 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001240
1241 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001242 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001243 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001244 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001246 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001247
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001248 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001249
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001250 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1252 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001253
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001254 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001255 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001256 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001257
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001258cleanup:
1259 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001260}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001261
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001262/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001263 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001264 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001265 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 * 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 +01001267 * bring the result back to this range.
1268 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001269 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001270 */
1271
1272/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 * 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 +01001274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001276#define INC_MUL_COUNT mul_count++;
1277#else
1278#define INC_MUL_COUNT
1279#endif
1280
Hanno Beckerd6028a12018-10-15 12:01:35 +01001281#define MOD_MUL( N ) \
1282 do \
1283 { \
1284 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1285 INC_MUL_COUNT \
1286 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001287
1288/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001290 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001291 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001292#define MOD_SUB( N ) \
1293 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1294 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001295
1296/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 * 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 +02001298 * We known P, N and the result are positive, so sub_abs is correct, and
1299 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001300 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001301#define MOD_ADD( N ) \
1302 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001304
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001305#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001306/*
1307 * For curves in short Weierstrass form, we do all the internal operations in
1308 * Jacobian coordinates.
1309 *
1310 * For multiplication, we'll use a comb method with coutermeasueres against
1311 * SPA, hence timing attacks.
1312 */
1313
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001314/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001315 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001316 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001319{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001320 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001322
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001324 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001325
Janos Follathb0697532016-08-18 12:38:46 +01001326#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001327 if( mbedtls_internal_ecp_grp_capable( grp ) )
1328 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001329#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001331 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001332
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001333 /*
1334 * X = X / Z^2 mod p
1335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1338 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 +01001339
1340 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001341 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001343 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1344 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 +01001345
1346 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001347 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001350
1351cleanup:
1352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001354
1355 return( ret );
1356}
1357
1358/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001359 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001360 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001361 * (See for example Cohen's "A Course in Computational Algebraic Number
1362 * Theory", Algorithm 10.3.4.)
1363 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001364 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001365 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001366 *
1367 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001370 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001371{
1372 int ret;
1373 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001375
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001376 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001377 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001378
Janos Follathb0697532016-08-18 12:38:46 +01001379#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001380 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001381 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001382#endif
1383
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001384 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001385 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001386
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001387 for( i = 0; i < T_size; i++ )
1388 mbedtls_mpi_init( &c[i] );
1389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001391
1392 /*
1393 * c[i] = Z_0 * ... * Z_i
1394 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001396 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001397 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001399 MOD_MUL( c[i] );
1400 }
1401
1402 /*
1403 * u = 1 / (Z_0 * ... * Z_n) mod P
1404 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001405 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001406
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001407 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001408 {
1409 /*
1410 * Zi = 1 / Z_i mod p
1411 * u = 1 / (Z_0 * ... * Z_i) mod P
1412 */
1413 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001415 }
1416 else
1417 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1419 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001420 }
1421
1422 /*
1423 * proceed as in normalize()
1424 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1426 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1427 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1428 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 +01001429
1430 /*
1431 * Post-precessing: reclaim some memory by shrinking coordinates
1432 * - not storing Z (always 1)
1433 * - shrinking other coordinates, but still keeping the same number of
1434 * limbs as P, as otherwise it will too likely be regrown too fast.
1435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1437 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1438 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001439
1440 if( i == 0 )
1441 break;
1442 }
1443
1444cleanup:
1445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001447 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001448 mbedtls_mpi_free( &c[i] );
1449 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001450
1451 return( ret );
1452}
1453
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001454/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001455 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1456 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1459 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001460 unsigned char inv )
1461{
1462 int ret;
1463 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001464 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001467
1468 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001469 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1470 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1471 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001472
1473cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001474 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001475
1476 return( ret );
1477}
1478
1479/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001480 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001481 *
Peter Dettmance661b22015-02-07 14:43:51 +07001482 * 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 +01001483 *
Peter Dettmance661b22015-02-07 14:43:51 +07001484 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1485 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1486 *
1487 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1488 *
1489 * Cost: 1D := 3M + 4S (A == 0)
1490 * 4M + 4S (A == -3)
1491 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1494 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001495{
1496 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001497 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001500 dbl_count++;
1501#endif
1502
Janos Follathb0697532016-08-18 12:38:46 +01001503#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001504 if( mbedtls_internal_ecp_grp_capable( grp ) )
1505 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001506#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001507
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001508 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 +01001509
1510 /* Special case for A = -3 */
1511 if( grp->A.p == NULL )
1512 {
Peter Dettmance661b22015-02-07 14:43:51 +07001513 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001514 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1515 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1516 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1517 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1518 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001519 }
1520 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001521 {
Peter Dettmance661b22015-02-07 14:43:51 +07001522 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001523 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1524 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001525
1526 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001527 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001528 {
1529 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001530 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1531 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1532 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1533 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001534 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001535 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001536
Peter Dettmance661b22015-02-07 14:43:51 +07001537 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001538 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1539 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1540 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1541 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001542
Peter Dettmance661b22015-02-07 14:43:51 +07001543 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001544 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1545 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001546
1547 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001548 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1549 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1550 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001551
1552 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001553 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1554 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1555 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001556
1557 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001558 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001560
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001564
1565cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001566 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 +02001567
1568 return( ret );
1569}
1570
1571/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001572 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001573 *
1574 * The coordinates of Q must be normalized (= affine),
1575 * but those of P don't need to. R is not normalized.
1576 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001577 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001578 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001579 * - at each step, P, Q and R are multiples of the base point, the factor
1580 * being less than its order, so none of them is zero;
1581 * - Q is an odd multiple of the base point, P an even multiple,
1582 * due to the choice of precomputed points in the modified comb method.
1583 * So branches for these cases do not leak secret information.
1584 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001585 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1586 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001587 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001588 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001589static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1590 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001591{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001592 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001596 add_count++;
1597#endif
1598
Janos Follathb0697532016-08-18 12:38:46 +01001599#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001600 if( mbedtls_internal_ecp_grp_capable( grp ) )
1601 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001602#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001603
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001604 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001605 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1608 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001610 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1611 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001612
1613 /*
1614 * Make sure Q coordinates are normalized
1615 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001616 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1617 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001619 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1620 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1623 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1624 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1625 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1626 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1627 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001628
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001629 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001630 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001631 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001632 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001633 {
1634 ret = ecp_double_jac( grp, R, P );
1635 goto cleanup;
1636 }
1637 else
1638 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001640 goto cleanup;
1641 }
1642 }
1643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1645 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1646 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1647 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1648 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1649 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1650 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1651 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1652 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1653 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1655 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1658 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1659 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001660
1661cleanup:
1662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1664 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001665
1666 return( ret );
1667}
1668
1669/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001670 * Randomize jacobian coordinates:
1671 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001672 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001673 *
1674 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001677 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1678{
1679 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001681 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001682 int count = 0;
1683
Janos Follathb0697532016-08-18 12:38:46 +01001684#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001685 if( mbedtls_internal_ecp_grp_capable( grp ) )
1686 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001687#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001688
1689 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001691
1692 /* Generate l such that 1 < l < p */
1693 do
1694 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001695 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001697 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001699
1700 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001701 {
1702 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1703 goto cleanup;
1704 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001705 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001706 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001707
1708 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 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 +02001710
1711 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1713 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 +02001714
1715 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001716 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1717 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 +02001718
1719cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001720 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001721
1722 return( ret );
1723}
1724
1725/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001726 * Check and define parameters used by the comb method (see below for details)
1727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1729#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001730#endif
1731
1732/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001733#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001734
1735/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001737
1738/*
1739 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001740 *
1741 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001742 * modified version that provides resistance to SPA by avoiding zero
1743 * digits in the representation as in [3]. We modify the method further by
1744 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001745 * representation uses one more K_i, due to carries, but saves on the size of
1746 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001747 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001748 * Summary of the comb method and its modifications:
1749 *
1750 * - The goal is to compute m*P for some w*d-bit integer m.
1751 *
1752 * - The basic comb method splits m into the w-bit integers
1753 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1754 * index has residue i modulo d, and computes m * P as
1755 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1756 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1757 *
1758 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1759 * .. + 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]] ..,
1760 * thereby successively converting it into a form where all summands
1761 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1762 *
1763 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1764 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1765 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1766 * Performing and iterating this procedure for those x[i] that are even
1767 * (keeping track of carry), we can transform the original sum into one of the form
1768 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1769 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1770 * which is why we are only computing half of it in the first place in
1771 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1772 *
1773 * - For the sake of compactness, only the seven low-order bits of x[i]
1774 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001775 * 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 +02001776 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001777 *
1778 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001779 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001780 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001782 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1783 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001784 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001785static void ecp_comb_recode_core( unsigned char x[], size_t d,
1786 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001787{
1788 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001789 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001790
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001791 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001792
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001793 /* First get the classical comb values (except for x_d = 0) */
1794 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001795 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001796 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001797
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001798 /* Now make sure x_1 .. x_d are odd */
1799 c = 0;
1800 for( i = 1; i <= d; i++ )
1801 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001802 /* Add carry and update it */
1803 cc = x[i] & c;
1804 x[i] = x[i] ^ c;
1805 c = cc;
1806
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001807 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001808 adjust = 1 - ( x[i] & 0x01 );
1809 c |= x[i] & ( x[i-1] * adjust );
1810 x[i] = x[i] ^ ( x[i-1] * adjust );
1811 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001812 }
1813}
1814
1815/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001816 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001817 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001818 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001819 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001820 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1821 * 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 +01001822 *
1823 * 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 +02001824 *
1825 * Note: Even comb values (those where P would be omitted from the
1826 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001827 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001828 *
1829 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001830 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001831 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1832 * (3) [add] Computation of all T[i]
1833 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001834 *
1835 * Step 1 can be interrupted but not the others; together with the final
1836 * coordinate normalization they are the largest steps done at once, depending
1837 * on the window size. Here are operation counts for P-256:
1838 *
1839 * step (2) (3) (4)
1840 * w = 5 142 165 208
1841 * w = 4 136 77 160
1842 * w = 3 130 33 136
1843 * w = 2 124 11 124
1844 *
1845 * So if ECC operations are blocking for too long even with a low max_ops
1846 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1847 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001848 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1850 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001851 unsigned char w, size_t d,
1852 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001853{
1854 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001855 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001856 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001857 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001859
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001860#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001861 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001862 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001863 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1864 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001865 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001866 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001867 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1868 goto add;
1869 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1870 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001871 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001872#else
1873 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001874#endif
1875
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001876#if defined(MBEDTLS_ECP_RESTARTABLE)
1877 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1878 {
1879 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1880
1881 /* initial state for the loop */
1882 rs_ctx->rsm->i = 0;
1883 }
1884
1885dbl:
1886#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001887 /*
1888 * Set T[0] = P and
1889 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1890 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001892
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001893#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001894 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1895 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001896 else
1897#endif
1898 j = 0;
1899
1900 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001901 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001902 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001903
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001904 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001905 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001906
1907 if( j % d == 0 )
1908 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1909
1910 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001911 }
1912
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001913#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001914 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1915 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1916
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001917norm_dbl:
1918#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001919 /*
1920 * Normalize current elements in T. As T has holes,
1921 * use an auxiliary array of pointers to elements in T.
1922 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001923 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001924 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001925 TT[j++] = T + i;
1926
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001927 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001928
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001929 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001930
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001931#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001932 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1933 rs_ctx->rsm->state = ecp_rsm_pre_add;
1934
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001935add:
1936#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001937 /*
1938 * Compute the remaining ones using the minimal number of additions
1939 * Be careful to update T[2^l] only after using it!
1940 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001941 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001942
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001943 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001944 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001945 j = i;
1946 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001947 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001948 }
1949
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001950#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001951 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1952 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1953
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001954norm_add:
1955#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001956 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02001957 * Normalize final elements in T. Even though there are no holes now, we
1958 * still need the auxiliary array for homogeneity with the previous
1959 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001960 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001961 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001962 TT[j] = T + j + 1;
1963
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001964 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001965
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001966 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001967
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001968cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001969#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001970 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
1971 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001972 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001973 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001974 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001975 }
1976#endif
Janos Follathb0697532016-08-18 12:38:46 +01001977
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001978 return( ret );
1979}
1980
1981/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001982 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001983 *
1984 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001985 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001986static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001987 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001988 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001989{
1990 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001991 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001992
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001993 /* Ignore the "sign" bit and scale down */
1994 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001995
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001996 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001997 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001998 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001999 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2000 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002001 }
2002
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002003 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002004 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002005
2006cleanup:
2007 return( ret );
2008}
2009
2010/*
2011 * Core multiplication algorithm for the (modified) comb method.
2012 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002013 *
2014 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002016static int ecp_mul_comb_core( 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é-Gonnard70c14372013-11-20 20:07:26 +01002018 const unsigned char x[], size_t d,
2019 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002020 void *p_rng,
2021 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002022{
2023 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002025 size_t i;
2026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002027 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002028
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002029#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002030 (void) rs_ctx;
2031#endif
2032
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002033#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002034 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2035 rs_ctx->rsm->state != ecp_rsm_comb_core )
2036 {
2037 rs_ctx->rsm->i = 0;
2038 rs_ctx->rsm->state = ecp_rsm_comb_core;
2039 }
2040
2041 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002042 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002043 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002044 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2045 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002046 }
2047 else
2048#endif
2049 {
2050 /* Start with a non-zero point and randomize its coordinates */
2051 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002052 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002053 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002054#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002055 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002056#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002057 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2058 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002059
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002060 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002061 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002062 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002063 --i;
2064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002066 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002068 }
2069
2070cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002073
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002074#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002075 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2076 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002077 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002078 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002079 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002080 }
2081#endif
2082
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002083 return( ret );
2084}
2085
2086/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002087 * Recode the scalar to get constant-time comb multiplication
2088 *
2089 * As the actual scalar recoding needs an odd scalar as a starting point,
2090 * this wrapper ensures that by replacing m by N - m if necessary, and
2091 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002092 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002093 * This works because we only support large prime order for Short Weierstrass
2094 * curves, so N is always odd hence either m or N - m is.
2095 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002096 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002097 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002098static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2099 const mbedtls_mpi *m,
2100 unsigned char k[COMB_MAX_D + 1],
2101 size_t d,
2102 unsigned char w,
2103 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002104{
2105 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002106 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002107
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002108 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002109 mbedtls_mpi_init( &mm );
2110
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002111 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002112 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2113 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2114
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002115 /* do we need the parity trick? */
2116 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2117
2118 /* execute parity fix in constant time */
2119 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002120 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002121 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2122
2123 /* actual scalar recoding */
2124 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002125
2126cleanup:
2127 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002128 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002129
2130 return( ret );
2131}
2132
2133/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002134 * Perform comb multiplication (for short Weierstrass curves)
2135 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002136 *
2137 * Scalar recoding may use a parity trick that makes us compute -m * P,
2138 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002139 */
2140static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2141 mbedtls_ecp_point *R,
2142 const mbedtls_mpi *m,
2143 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002144 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002145 unsigned char w,
2146 size_t d,
2147 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002148 void *p_rng,
2149 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002150{
2151 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002152 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002153 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002154 mbedtls_ecp_point *RR = R;
2155
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002156#if defined(MBEDTLS_ECP_RESTARTABLE)
2157 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2158 {
2159 RR = &rs_ctx->rsm->R;
2160
2161 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2162 goto final_norm;
2163 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002164#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002165
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002166 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2167 &parity_trick ) );
2168 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2169 f_rng, p_rng, rs_ctx ) );
2170 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2171
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002172#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002173 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002174 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002175
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002176final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002177 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002178#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002179 /*
2180 * Knowledge of the jacobian coordinates may leak the last few bits of the
2181 * scalar [1], and since our MPI implementation isn't constant-flow,
2182 * inversion (used for coordinate normalization) may leak the full value
2183 * of its input via side-channels [2].
2184 *
2185 * [1] https://eprint.iacr.org/2003/191
2186 * [2] https://eprint.iacr.org/2020/055
2187 *
2188 * Avoid the leak by randomizing coordinates before we normalize them.
2189 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002190#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002191 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002192#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002193 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2194
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002195 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2196
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002197#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002198 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2199 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002200#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002201
2202cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002203 return( ret );
2204}
2205
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002206/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002207 * Pick window size based on curve size and whether we optimize for base point
2208 */
2209static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2210 unsigned char p_eq_g )
2211{
2212 unsigned char w;
2213
2214 /*
2215 * Minimize the number of multiplications, that is minimize
2216 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2217 * (see costs of the various parts, with 1S = 1M)
2218 */
2219 w = grp->nbits >= 384 ? 5 : 4;
2220
2221 /*
2222 * If P == G, pre-compute a bit more, since this may be re-used later.
2223 * Just adding one avoids upping the cost of the first mul too much,
2224 * and the memory cost too.
2225 */
2226 if( p_eq_g )
2227 w++;
2228
2229 /*
2230 * Make sure w is within bounds.
2231 * (The last test is useful only for very small curves in the test suite.)
2232 */
2233 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2234 w = MBEDTLS_ECP_WINDOW_SIZE;
2235 if( w >= grp->nbits )
2236 w = 2;
2237
2238 return( w );
2239}
2240
2241/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002242 * Multiplication using the comb method - for curves in short Weierstrass form
2243 *
2244 * This function is mainly responsible for administrative work:
2245 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002246 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002247 * functions): allocation, computation, ownership tranfer, freeing.
2248 *
2249 * It delegates the actual arithmetic work to:
2250 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2251 *
2252 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002253 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002254static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2255 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002256 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002257 void *p_rng,
2258 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002259{
2260 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002261 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002262 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002263 unsigned char T_size = 0, T_ok = 0;
2264 mbedtls_ecp_point *T = NULL;
2265#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2266 ecp_drbg_context drbg_ctx;
2267
2268 ecp_drbg_init( &drbg_ctx );
2269#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002270
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002271 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002272
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002273#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2274 if( f_rng == NULL )
2275 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002276 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002277 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002278#if defined(MBEDTLS_ECP_RESTARTABLE)
2279 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2280 p_rng = &rs_ctx->rsm->drbg_ctx;
2281 else
2282#endif
2283 p_rng = &drbg_ctx;
2284
2285 /* Initialize internal DRBG if necessary */
2286#if defined(MBEDTLS_ECP_RESTARTABLE)
2287 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2288 rs_ctx->rsm->drbg_seeded == 0 )
2289#endif
2290 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002291 const size_t m_len = ( grp->nbits + 7 ) / 8;
2292 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002293 }
2294#if defined(MBEDTLS_ECP_RESTARTABLE)
2295 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2296 rs_ctx->rsm->drbg_seeded = 1;
2297#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002298 }
2299#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2300
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002301 /* Is P the base point ? */
2302#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2303 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2304 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002305#else
2306 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002307#endif
2308
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002309 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002310 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002311 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002312 d = ( grp->nbits + w - 1 ) / w;
2313
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002314 /* Pre-computed table: do we have it already for the base point? */
2315 if( p_eq_g && grp->T != NULL )
2316 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002317 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002318 T = grp->T;
2319 T_ok = 1;
2320 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002321 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002322#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002323 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002324 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002325 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002326 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002327 T = rs_ctx->rsm->T;
2328 rs_ctx->rsm->T = NULL;
2329 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002330
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002331 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002332 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002333 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002334 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002335#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002336 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002337 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002338 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002339 if( T == NULL )
2340 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002341 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002342 goto cleanup;
2343 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002344
2345 for( i = 0; i < T_size; i++ )
2346 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002347
2348 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002349 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002350
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002351 /* Compute table (or finish computing it) if not done already */
2352 if( !T_ok )
2353 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002354 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002355
2356 if( p_eq_g )
2357 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002358 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002359 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002360 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002361 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002362 }
2363 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002364
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002365 /* Actual comb multiplication using precomputed points */
2366 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002367 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002368 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002369
2370cleanup:
2371
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002372#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2373 ecp_drbg_free( &drbg_ctx );
2374#endif
2375
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002376 /* does T belong to the group? */
2377 if( T == grp->T )
2378 T = NULL;
2379
2380 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002381#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002382 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 +01002383 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002384 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002385 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002386 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002387 T = NULL;
2388 }
2389#endif
2390
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002391 /* did T belong to us? then let's destroy it! */
2392 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002393 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002394 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 mbedtls_ecp_point_free( &T[i] );
2396 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002397 }
2398
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002399 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002400#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002401 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2402#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002403 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002404 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002405 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002406
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002407 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002408
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002409 return( ret );
2410}
2411
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002412#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002413
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002414#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002415/*
2416 * For Montgomery curves, we do all the internal arithmetic in projective
2417 * coordinates. Import/export of points uses only the x coordinates, which is
2418 * internaly represented as X / Z.
2419 *
2420 * For scalar multiplication, we'll use a Montgomery ladder.
2421 */
2422
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002423/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002424 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2425 * Cost: 1M + 1I
2426 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002427static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002428{
2429 int ret;
2430
Janos Follathb0697532016-08-18 12:38:46 +01002431#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002432 if( mbedtls_internal_ecp_grp_capable( grp ) )
2433 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002434#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002436 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2437 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2438 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002439
2440cleanup:
2441 return( ret );
2442}
2443
2444/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002445 * Randomize projective x/z coordinates:
2446 * (X, Z) -> (l X, l Z) for random l
2447 * This is sort of the reverse operation of ecp_normalize_mxz().
2448 *
2449 * This countermeasure was first suggested in [2].
2450 * Cost: 2M
2451 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002452static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002453 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2454{
2455 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002456 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002457 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002458 int count = 0;
2459
Janos Follathb0697532016-08-18 12:38:46 +01002460#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002461 if( mbedtls_internal_ecp_grp_capable( grp ) )
2462 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002463#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002464
2465 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002466 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002467
2468 /* Generate l such that 1 < l < p */
2469 do
2470 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002471 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2474 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002475
2476 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002477 {
2478 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2479 goto cleanup;
2480 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002481 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2485 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 +01002486
2487cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002489
2490 return( ret );
2491}
2492
2493/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002494 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2495 * for Montgomery curves in x/z coordinates.
2496 *
2497 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2498 * with
2499 * d = X1
2500 * P = (X2, Z2)
2501 * Q = (X3, Z3)
2502 * R = (X4, Z4)
2503 * S = (X5, Z5)
2504 * and eliminating temporary variables tO, ..., t4.
2505 *
2506 * Cost: 5M + 4S
2507 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2509 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2510 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2511 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002512{
2513 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002515
Janos Follathb0697532016-08-18 12:38:46 +01002516#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002517 if( mbedtls_internal_ecp_grp_capable( grp ) )
2518 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002519#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2522 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2523 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2526 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2527 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2528 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2529 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2530 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2531 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2532 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2533 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2534 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2535 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2536 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2537 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2538 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2539 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2540 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2541 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2542 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 +01002543
2544cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2546 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2547 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002548
2549 return( ret );
2550}
2551
2552/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002553 * Multiplication with Montgomery ladder in x/z coordinates,
2554 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2557 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002558 int (*f_rng)(void *, unsigned char *, size_t),
2559 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002560{
2561 int ret;
2562 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002563 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002564 mbedtls_ecp_point RP;
2565 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002566#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2567 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002568
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002569 ecp_drbg_init( &drbg_ctx );
2570#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002572
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002573#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2574 if( f_rng == NULL )
2575 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002576 const size_t m_len = ( grp->nbits + 7 ) / 8;
2577 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002578 f_rng = &ecp_drbg_random;
2579 p_rng = &drbg_ctx;
2580 }
2581#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2582
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002583 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002584 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2585 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002586
2587 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002588 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2590 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002591
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002592 /* RP.X might be sligtly larger than P, so reduce it */
2593 MOD_ADD( RP.X );
2594
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002595 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002596#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002597 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002598#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002599 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002600
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002601 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002602 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002603 while( i-- > 0 )
2604 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002605 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002606 /*
2607 * if (b) R = 2R + P else R = 2R,
2608 * which is:
2609 * if (b) double_add( RP, R, RP, R )
2610 * else double_add( R, RP, R, RP )
2611 * but using safe conditional swaps to avoid leaks
2612 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2614 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2615 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2616 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2617 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002618 }
2619
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002620 /*
2621 * Knowledge of the projective coordinates may leak the last few bits of the
2622 * scalar [1], and since our MPI implementation isn't constant-flow,
2623 * inversion (used for coordinate normalization) may leak the full value
2624 * of its input via side-channels [2].
2625 *
2626 * [1] https://eprint.iacr.org/2003/191
2627 * [2] https://eprint.iacr.org/2020/055
2628 *
2629 * Avoid the leak by randomizing coordinates before we normalize them.
2630 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002631#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002632 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002633#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002634 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002637
2638cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002639#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2640 ecp_drbg_free( &drbg_ctx );
2641#endif
2642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002643 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002644
2645 return( ret );
2646}
2647
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002648#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002649
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002650/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002651 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002652 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002653int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002654 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002655 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2656 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002657{
Janos Follathb0697532016-08-18 12:38:46 +01002658 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002659#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2660 char is_grp_capable = 0;
2661#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002662 ECP_VALIDATE_RET( grp != NULL );
2663 ECP_VALIDATE_RET( R != NULL );
2664 ECP_VALIDATE_RET( m != NULL );
2665 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002666
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002667#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002668 /* reset ops count for this call if top-level */
2669 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2670 rs_ctx->ops_done = 0;
2671#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002672
Janos Follathc44ab972016-11-18 16:38:23 +00002673#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002674 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002675 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002676#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002677
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002678#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002679 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002680 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002681#endif
2682 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002683 /* check_privkey is free */
2684 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2685
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002686 /* Common sanity checks */
2687 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2688 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002689 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002690
2691 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002692#if defined(ECP_MONTGOMERY)
2693 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002694 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002695#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002696#if defined(ECP_SHORTWEIERSTRASS)
2697 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002698 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002699#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002700
Janos Follath6c8ccd52016-11-29 15:37:09 +00002701cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002702
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002703#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002704 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002705 mbedtls_internal_ecp_free( 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é-Gonnard4b9c51e2017-04-20 15:50:26 +02002708#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002709 if( rs_ctx != NULL )
2710 rs_ctx->depth--;
2711#endif
2712
Janos Follathb0697532016-08-18 12:38:46 +01002713 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002714}
2715
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002716/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002717 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002718 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002719int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002720 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002721 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002722{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002723 ECP_VALIDATE_RET( grp != NULL );
2724 ECP_VALIDATE_RET( R != NULL );
2725 ECP_VALIDATE_RET( m != NULL );
2726 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002727 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002728}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002729
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002730#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002731/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002732 * Check that an affine point is valid as a public key,
2733 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002735static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002736{
2737 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002738 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002739
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002740 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002741 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2742 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2743 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2744 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2745 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002747 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002748
2749 /*
2750 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002751 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002752 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002753 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2754 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002755
2756 /* Special case for A = -3 */
2757 if( grp->A.p == NULL )
2758 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002759 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002760 }
2761 else
2762 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002763 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002764 }
2765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002766 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2767 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002769 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2770 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002771
2772cleanup:
2773
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002774 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002775
2776 return( ret );
2777}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002778#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002779
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002780/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002781 * R = m * P with shortcuts for m == 1 and m == -1
2782 * NOT constant-time - ONLY for short Weierstrass!
2783 */
2784static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2785 mbedtls_ecp_point *R,
2786 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002787 const mbedtls_ecp_point *P,
2788 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002789{
2790 int ret;
2791
2792 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2793 {
2794 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2795 }
2796 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2797 {
2798 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2799 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2800 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2801 }
2802 else
2803 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002804 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2805 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002806 }
2807
2808cleanup:
2809 return( ret );
2810}
2811
2812/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002813 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002814 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002815 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002816int mbedtls_ecp_muladd_restartable(
2817 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002818 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002819 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2820 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002821{
2822 int ret;
2823 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002824 mbedtls_ecp_point *pmP = &mP;
2825 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002826#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2827 char is_grp_capable = 0;
2828#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002829 ECP_VALIDATE_RET( grp != NULL );
2830 ECP_VALIDATE_RET( R != NULL );
2831 ECP_VALIDATE_RET( m != NULL );
2832 ECP_VALIDATE_RET( P != NULL );
2833 ECP_VALIDATE_RET( n != NULL );
2834 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002835
2836 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2837 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2838
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002839 mbedtls_ecp_point_init( &mP );
2840
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002841 ECP_RS_ENTER( ma );
2842
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002843#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002844 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2845 {
2846 /* redirect intermediate results to restart context */
2847 pmP = &rs_ctx->ma->mP;
2848 pR = &rs_ctx->ma->R;
2849
2850 /* jump to next operation */
2851 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2852 goto mul2;
2853 if( rs_ctx->ma->state == ecp_rsma_add )
2854 goto add;
2855 if( rs_ctx->ma->state == ecp_rsma_norm )
2856 goto norm;
2857 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002858#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002859
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002860 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002861#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002862 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002863 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002864
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002865mul2:
2866#endif
2867 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002868
2869#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2870 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2871 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2872#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2873
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002874#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002875 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002876 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002877
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002878add:
2879#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002880 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002881 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002882#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002883 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002884 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002885
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002886norm:
2887#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002888 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002889 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2890
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002891#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002892 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2893 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2894#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002895
2896cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002897#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002898 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002899 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002900#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002901
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002902 mbedtls_ecp_point_free( &mP );
2903
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002904 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002905
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002906 return( ret );
2907}
2908
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002909/*
2910 * Linear combination
2911 * NOT constant-time
2912 */
2913int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2914 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2915 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2916{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002917 ECP_VALIDATE_RET( grp != NULL );
2918 ECP_VALIDATE_RET( R != NULL );
2919 ECP_VALIDATE_RET( m != NULL );
2920 ECP_VALIDATE_RET( P != NULL );
2921 ECP_VALIDATE_RET( n != NULL );
2922 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002923 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2924}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002925
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002926#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002927/*
2928 * Check validity of a public key for Montgomery curves with x-only schemes
2929 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002930static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002931{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002932 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002933 /* Allow any public value, if it's too big then we'll just reduce it mod p
2934 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002935 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2936 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002937
2938 return( 0 );
2939}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002940#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002941
2942/*
2943 * Check that a point is valid as a public key
2944 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002945int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2946 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002947{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002948 ECP_VALIDATE_RET( grp != NULL );
2949 ECP_VALIDATE_RET( pt != NULL );
2950
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002951 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002952 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2953 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002954
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002955#if defined(ECP_MONTGOMERY)
2956 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002957 return( ecp_check_pubkey_mx( grp, pt ) );
2958#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002959#if defined(ECP_SHORTWEIERSTRASS)
2960 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002961 return( ecp_check_pubkey_sw( grp, pt ) );
2962#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002963 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002964}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002965
2966/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002967 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002968 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002969int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
2970 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002971{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002972 ECP_VALIDATE_RET( grp != NULL );
2973 ECP_VALIDATE_RET( d != NULL );
2974
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002975#if defined(ECP_MONTGOMERY)
2976 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002977 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002978 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002979 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2980 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002981 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002982 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002983
2984 /* see [Curve25519] page 5 */
2985 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
2986 return( MBEDTLS_ERR_ECP_INVALID_KEY );
2987
2988 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002989 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002990#endif /* ECP_MONTGOMERY */
2991#if defined(ECP_SHORTWEIERSTRASS)
2992 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002993 {
2994 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002995 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2996 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2997 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002998 else
2999 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003000 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003001#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003003 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003004}
3005
3006/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003007 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003008 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003009int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3010 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003011 int (*f_rng)(void *, unsigned char *, size_t),
3012 void *p_rng )
3013{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003014 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003015 size_t n_size;
3016
3017 ECP_VALIDATE_RET( grp != NULL );
3018 ECP_VALIDATE_RET( d != NULL );
3019 ECP_VALIDATE_RET( f_rng != NULL );
3020
3021 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003022
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003023#if defined(ECP_MONTGOMERY)
3024 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003025 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003026 /* [M225] page 5 */
3027 size_t b;
3028
Janos Follath98e28a72016-05-31 14:03:54 +01003029 do {
3030 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3031 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003032
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003033 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003034 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003035 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003036 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003037 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003038 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003039
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003040 /* Make sure the last two bits are unset for Curve448, three bits for
3041 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003042 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3043 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003044 if( grp->nbits == 254 )
3045 {
3046 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3047 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003048 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003049#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003050
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003051#if defined(ECP_SHORTWEIERSTRASS)
3052 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003053 {
3054 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003055 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003056 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003057
3058 /*
3059 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3060 * - use the same byte ordering;
3061 * - keep the leftmost nbits bits of the generated octet string;
3062 * - try until result is in the desired range.
3063 * This also avoids any biais, which is especially important for ECDSA.
3064 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003065 do
3066 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003067 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003068 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003069
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003070 /*
3071 * Each try has at worst a probability 1/2 of failing (the msb has
3072 * a probability 1/2 of being 0, and then the result will be < N),
3073 * so after 30 tries failure probability is a most 2**(-30).
3074 *
3075 * For most curves, 1 try is enough with overwhelming probability,
3076 * since N starts with a lot of 1s in binary, but some curves
3077 * such as secp224k1 are actually very close to the worst case.
3078 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003079 if( ++count > 30 )
3080 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003081
Janos Follath867a3ab2019-10-11 14:21:53 +01003082 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003083 if( ret != 0 )
3084 {
3085 goto cleanup;
3086 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003087 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003088 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003089 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003090#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003091
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003092cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003093 return( ret );
3094}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003095
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003096/*
3097 * Generate a keypair with configurable base point
3098 */
3099int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3100 const mbedtls_ecp_point *G,
3101 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3102 int (*f_rng)(void *, unsigned char *, size_t),
3103 void *p_rng )
3104{
3105 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003106 ECP_VALIDATE_RET( grp != NULL );
3107 ECP_VALIDATE_RET( d != NULL );
3108 ECP_VALIDATE_RET( G != NULL );
3109 ECP_VALIDATE_RET( Q != NULL );
3110 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003111
3112 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3113 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3114
3115cleanup:
3116 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003117}
3118
3119/*
3120 * Generate key pair, wrapper for conventional base point
3121 */
3122int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3123 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3124 int (*f_rng)(void *, unsigned char *, size_t),
3125 void *p_rng )
3126{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003127 ECP_VALIDATE_RET( grp != NULL );
3128 ECP_VALIDATE_RET( d != NULL );
3129 ECP_VALIDATE_RET( Q != NULL );
3130 ECP_VALIDATE_RET( f_rng != NULL );
3131
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003132 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003133}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003134
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003135/*
3136 * Generate a keypair, prettier wrapper
3137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003138int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003139 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3140{
3141 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003142 ECP_VALIDATE_RET( key != NULL );
3143 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003144
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003145 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003146 return( ret );
3147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003148 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003149}
3150
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003151/*
3152 * Check a public-private key pair
3153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003154int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003155{
3156 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003157 mbedtls_ecp_point Q;
3158 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003159 ECP_VALIDATE_RET( pub != NULL );
3160 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003162 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003163 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003164 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3165 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3166 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003167 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003168 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003169 }
3170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003171 mbedtls_ecp_point_init( &Q );
3172 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003174 /* mbedtls_ecp_mul() needs a non-const group... */
3175 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003176
3177 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003178 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003180 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3181 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3182 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003183 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003184 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003185 goto cleanup;
3186 }
3187
3188cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003189 mbedtls_ecp_point_free( &Q );
3190 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003191
3192 return( ret );
3193}
3194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003195#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003196
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003197#if defined(ECP_ONE_STEP_KDF)
3198/*
3199 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3200 * but unofficial ones can be found at:
3201 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3202 *
3203 * We only use the ones with empty fixedInfo, and for brevity's sake, only
3204 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
3205 * exactly one block, and with SHA-512 less than one block).
3206 */
3207#if defined(MBEDTLS_SHA512_C)
3208
3209static const uint8_t test_kdf_z[16] = {
3210 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
3211 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
3212};
3213static const uint8_t test_kdf_out[32] = {
3214 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
3215 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
3216 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
3217 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
3218};
3219
3220#elif defined(MBEDTLS_SHA256_C)
3221
3222static const uint8_t test_kdf_z[16] = {
3223 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
3224 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
3225};
3226static const uint8_t test_kdf_out[32] = {
3227 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
3228 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
3229 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
3230 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
3231};
3232
3233#elif defined(MBEDTLS_SHA1_C)
3234
3235static const uint8_t test_kdf_z[16] = {
3236 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
3237 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
3238};
3239static const uint8_t test_kdf_out[32] = {
3240 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
3241 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
3242 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
3243 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
3244};
3245
3246#else
3247#error "Need at least one of SHA-512, SHA-256 or SHA-1"
3248#endif
3249
3250static int ecp_kdf_self_test( void )
3251{
3252 int ret;
3253 ecp_drbg_context kdf_ctx;
3254 mbedtls_mpi scalar;
3255 uint8_t out[sizeof( test_kdf_out )];
3256
3257 ecp_drbg_init( &kdf_ctx );
3258 mbedtls_mpi_init( &scalar );
3259 memset( out, 0, sizeof( out ) );
3260
3261 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3262 test_kdf_z, sizeof( test_kdf_z ) ) );
3263
3264 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3265 &scalar, sizeof( test_kdf_z ) ) );
3266
3267 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3268
3269 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3270 ret = -1;
3271
3272cleanup:
3273 ecp_drbg_free( &kdf_ctx );
3274 mbedtls_mpi_free( &scalar );
3275
3276 return( ret );
3277}
3278#endif /* ECP_ONE_STEP_KDF */
3279
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003280/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003281 * Checkup routine
3282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003283int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003284{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003285 int ret;
3286 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003287 mbedtls_ecp_group grp;
3288 mbedtls_ecp_point R, P;
3289 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003290 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003291 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003292 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003293 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003294 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003295 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003296 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003297 "400000000000000000000000000000000000000000000000", /* one and zeros */
3298 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3299 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003300 };
3301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003302 mbedtls_ecp_group_init( &grp );
3303 mbedtls_ecp_point_init( &R );
3304 mbedtls_ecp_point_init( &P );
3305 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003306
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003307 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003308#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003309 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003310#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003311 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003312#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003313
3314 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003315 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003316
3317 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003318 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3319 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003320
3321 add_count = 0;
3322 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003323 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003324 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3325 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003326
3327 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3328 {
3329 add_c_prev = add_count;
3330 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003331 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003332 add_count = 0;
3333 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003334 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003336 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3337 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003338
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003339 if( add_count != add_c_prev ||
3340 dbl_count != dbl_c_prev ||
3341 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003342 {
3343 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003344 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003345
3346 ret = 1;
3347 goto cleanup;
3348 }
3349 }
3350
3351 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003352 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003353
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003354 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003355 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003356 /* We computed P = 2G last time, use it */
3357
3358 add_count = 0;
3359 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003360 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003361 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3362 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003363
3364 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3365 {
3366 add_c_prev = add_count;
3367 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003368 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003369 add_count = 0;
3370 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003371 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003372
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003373 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3374 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003375
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003376 if( add_count != add_c_prev ||
3377 dbl_count != dbl_c_prev ||
3378 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003379 {
3380 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003381 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003382
3383 ret = 1;
3384 goto cleanup;
3385 }
3386 }
3387
3388 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003389 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003390
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003391#if defined(ECP_ONE_STEP_KDF)
3392 if( verbose != 0 )
3393 mbedtls_printf( " ECP test #3 (internal KDF): " );
3394
3395 ret = ecp_kdf_self_test();
3396 if( ret != 0 )
3397 {
3398 if( verbose != 0 )
3399 mbedtls_printf( "failed\n" );
3400
3401 ret = 1;
3402 goto cleanup;
3403 }
3404
3405 if( verbose != 0 )
3406 mbedtls_printf( "passed\n" );
3407#endif /* ECP_ONE_STEP_KDF */
3408
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003409cleanup:
3410
3411 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003412 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003414 mbedtls_ecp_group_free( &grp );
3415 mbedtls_ecp_point_free( &R );
3416 mbedtls_ecp_point_free( &P );
3417 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003418
3419 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003420 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003421
3422 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003423}
3424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003425#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003426
Janos Follathb0697532016-08-18 12:38:46 +01003427#endif /* !MBEDTLS_ECP_ALT */
3428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003429#endif /* MBEDTLS_ECP_C */