blob: a7486c198ab7b7d3c8115cd124b68c54779a3b7a [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 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010045 */
46
47/*
48 * References:
49 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010050 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010051 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010052 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010053 * RFC 4492 for the related TLS structures and constants
Nicholas Wilson08f3ef12015-11-10 13:10:01 +000054 * RFC 7748 for the Curve448 and Curve25519 curve definitions
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020055 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020056 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010057 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020058 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020059 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
60 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
61 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010062 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020063 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010064 * render ECC resistant against Side Channel Attacks. IACR Cryptology
65 * ePrint Archive, 2004, vol. 2004, p. 342.
66 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010067 */
68
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000070#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020071#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020073#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010074
Janos Follath683c5822018-12-07 12:09:25 +000075/**
76 * \brief Function level alternative implementation.
77 *
78 * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
79 * replace certain functions in this module. The alternative implementations are
80 * typically hardware accelerators and need to activate the hardware before the
81 * computation starts and deactivate it after it finishes. The
82 * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
83 * this purpose.
84 *
85 * To preserve the correct functionality the following conditions must hold:
86 *
87 * - The alternative implementation must be activated by
88 * mbedtls_internal_ecp_init() before any of the replaceable functions is
89 * called.
90 * - mbedtls_internal_ecp_free() must \b only be called when the alternative
91 * implementation is activated.
92 * - mbedtls_internal_ecp_init() must \b not be called when the alternative
93 * implementation is activated.
94 * - Public functions must not return while the alternative implementation is
95 * activated.
96 * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
97 * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
98 * \endcode ensures that the alternative implementation supports the current
99 * group.
100 */
101#if defined(MBEDTLS_ECP_INTERNAL_ALT)
102#endif
103
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200104#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100105
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000106#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +0000107#include "mbedtls/threading.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500108#include "mbedtls/platform_util.h"
Janos Follath7d34e2e2021-06-24 14:48:38 +0100109#include "mbedtls/bn_mul.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200110
Rich Evans00ab4702015-02-06 13:43:58 +0000111#include <string.h>
112
Janos Follathb0697532016-08-18 12:38:46 +0100113#if !defined(MBEDTLS_ECP_ALT)
114
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000115/* Parameter validation macros based on platform_util.h */
116#define ECP_VALIDATE_RET( cond ) \
117 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
118#define ECP_VALIDATE( cond ) \
119 MBEDTLS_INTERNAL_VALIDATE( cond )
120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000122#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200123#else
Rich Evans00ab4702015-02-06 13:43:58 +0000124#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +0000125#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200126#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200127#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +0200129#endif
130
Janos Follath47d28f02016-11-01 13:22:05 +0000131#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +0100132
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200133#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200134#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200135#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200136#elif defined(MBEDTLS_CTR_DRBG_C)
137#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200138#elif defined(MBEDTLS_SHA512_C)
139#include "mbedtls/sha512.h"
140#elif defined(MBEDTLS_SHA256_C)
141#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200142#else
143#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
144#endif
145#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
146
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100147#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
148 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100149#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200150#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100153/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100154 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200155 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100156 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100157static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100158#endif
159
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200160#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
161/*
162 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200163 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200164 * that people will pass non-NULL RNG when they care about side-channels, but
165 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
166 * no opportunity for the user to do anything about it.
167 *
168 * The obvious strategies for addressing that include:
169 * - change those APIs so that they take RNG arguments;
170 * - require a global RNG to be available to all crypto modules.
171 *
172 * Unfortunately those would break compatibility. So what we do instead is
173 * have our own internal DRBG instance, seeded from the secret scalar.
174 *
175 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200176 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200177 */
178
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200179#if defined(MBEDTLS_HMAC_DRBG_C)
180
181/* DRBG context type */
182typedef mbedtls_hmac_drbg_context ecp_drbg_context;
183
184/* DRBG context init */
185static inline void ecp_drbg_init( ecp_drbg_context *ctx )
186{
187 mbedtls_hmac_drbg_init( ctx );
188}
189
190/* DRBG context free */
191static inline void ecp_drbg_free( ecp_drbg_context *ctx )
192{
193 mbedtls_hmac_drbg_free( ctx );
194}
195
196/* DRBG function */
197static inline int ecp_drbg_random( void *p_rng,
198 unsigned char *output, size_t output_len )
199{
200 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
201}
202
203/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200204static int ecp_drbg_seed( ecp_drbg_context *ctx,
205 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200206{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200207 int ret;
208 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200209 /* The list starts with strong hashes */
210 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
211 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
212
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200213 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
214 secret_bytes, secret_len ) );
215
216 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
217
218cleanup:
219 mbedtls_platform_zeroize( secret_bytes, secret_len );
220
221 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200222}
223
224#elif defined(MBEDTLS_CTR_DRBG_C)
225
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200226/* DRBG context type */
227typedef mbedtls_ctr_drbg_context ecp_drbg_context;
228
229/* DRBG context init */
230static inline void ecp_drbg_init( ecp_drbg_context *ctx )
231{
232 mbedtls_ctr_drbg_init( ctx );
233}
234
235/* DRBG context free */
236static inline void ecp_drbg_free( ecp_drbg_context *ctx )
237{
238 mbedtls_ctr_drbg_free( ctx );
239}
240
241/* DRBG function */
242static inline int ecp_drbg_random( void *p_rng,
243 unsigned char *output, size_t output_len )
244{
245 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
246}
247
248/*
249 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
250 * we need to pass an entropy function when seeding. So we use a dummy
251 * function for that, and pass the actual entropy as customisation string.
252 * (During seeding of CTR_DRBG the entropy input and customisation string are
253 * concatenated before being used to update the secret state.)
254 */
255static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
256{
257 (void) ctx;
258 memset( out, 0, len );
259 return( 0 );
260}
261
262/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200263static int ecp_drbg_seed( ecp_drbg_context *ctx,
264 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200265{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200266 int ret;
267 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200268
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200269 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
270 secret_bytes, secret_len ) );
271
272 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
273 secret_bytes, secret_len );
274
275cleanup:
276 mbedtls_platform_zeroize( secret_bytes, secret_len );
277
278 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200279}
280
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200281#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200282
283/* This will be used in the self-test function */
284#define ECP_ONE_STEP_KDF
285
286/*
287 * We need to expand secret data (the scalar) into a longer stream of bytes.
288 *
289 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
290 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
291 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
292 *
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200293 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200294 */
295#if defined(MBEDTLS_SHA512_C)
296
297#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
298#define HASH_BLOCK_BYTES ( 512 / 8 )
299
300#elif defined(MBEDTLS_SHA256_C)
301
302#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
303#define HASH_BLOCK_BYTES ( 256 / 8 )
304
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200305#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200306
307/*
308 * State consists of a 32-bit counter plus the secret value.
309 *
310 * We stored them concatenated in a single buffer as that's what will get
311 * passed to the hash function.
312 */
313typedef struct {
314 size_t total_len;
315 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
316} ecp_drbg_context;
317
318static void ecp_drbg_init( ecp_drbg_context *ctx )
319{
320 memset( ctx, 0, sizeof( ecp_drbg_context ) );
321}
322
323static void ecp_drbg_free( ecp_drbg_context *ctx )
324{
325 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
326}
327
328static int ecp_drbg_seed( ecp_drbg_context *ctx,
329 const mbedtls_mpi *secret, size_t secret_len )
330{
331 ctx->total_len = 4 + secret_len;
332 memset( ctx->buf, 0, 4);
333 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
334}
335
336static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
337{
338 ecp_drbg_context *ctx = p_rng;
339 int ret;
340 size_t len_done = 0;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200341 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200342
343 while( len_done < output_len )
344 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200345 uint8_t use_len;
346
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200347 /* This function is only called for coordinate randomisation, which
348 * happens only twice in a scalar multiplication. Each time needs a
349 * random value in the range [2, p-1], and gets it by drawing len(p)
350 * bytes from this function, and retrying up to 10 times if unlucky.
351 *
352 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200353 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
354 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200355 *
356 * Since we don't need to draw more that 255 blocks, don't bother
357 * with carry propagation and just return an error instead. We can
358 * change that it we even need to draw more blinding values.
359 */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200360 ctx->buf[3] += 1;
361 if( ctx->buf[3] == 0 )
362 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
363
364 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
365 if( ret != 0 )
366 return( ret );
367
368 if( output_len - len_done > HASH_BLOCK_BYTES )
369 use_len = HASH_BLOCK_BYTES;
370 else
371 use_len = output_len - len_done;
372
373 memcpy( output + len_done, tmp, use_len );
374 len_done += use_len;
375 }
376
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200377 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
378
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200379 return( 0 );
380}
381
382#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200383#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200384#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200385#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
386
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200387#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100388/*
389 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200390 *
391 * Default value 0 means that ECC operations will not yield.
392 * Note that regardless of the value of ecp_max_ops, always at
393 * least one step is performed before yielding.
394 *
395 * Setting ecp_max_ops=1 can be suitable for testing purposes
396 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100397 */
398static unsigned ecp_max_ops = 0;
399
400/*
401 * Set ecp_max_ops
402 */
403void mbedtls_ecp_set_max_ops( unsigned max_ops )
404{
405 ecp_max_ops = max_ops;
406}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100407
408/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200409 * Check if restart is enabled
410 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200411int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200412{
413 return( ecp_max_ops != 0 );
414}
415
416/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200417 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100418 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200419struct mbedtls_ecp_restart_mul
420{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100421 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100422 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100423 mbedtls_ecp_point *T; /* table for precomputed points */
424 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200425 enum { /* what were we doing last time we returned? */
426 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
427 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100428 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
429 ecp_rsm_pre_add, /* precompute remaining points by adding */
430 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200431 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100432 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100433 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200434#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
435 ecp_drbg_context drbg_ctx;
436 unsigned char drbg_seeded;
437#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100438};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100439
440/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200441 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100442 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200443static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100444{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200445 mbedtls_ecp_point_init( &ctx->R );
446 ctx->i = 0;
447 ctx->T = NULL;
448 ctx->T_size = 0;
449 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200450#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
451 ecp_drbg_init( &ctx->drbg_ctx );
452 ctx->drbg_seeded = 0;
453#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100454}
455
456/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200457 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100458 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200459static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100460{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100461 unsigned char i;
462
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100463 if( ctx == NULL )
464 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100465
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100466 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100467
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200468 if( ctx->T != NULL )
469 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100470 for( i = 0; i < ctx->T_size; i++ )
471 mbedtls_ecp_point_free( ctx->T + i );
472 mbedtls_free( ctx->T );
473 }
474
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200475#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
476 ecp_drbg_free( &ctx->drbg_ctx );
477#endif
478
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200479 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100480}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100481
482/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200483 * Restart context for ecp_muladd()
484 */
485struct mbedtls_ecp_restart_muladd
486{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200487 mbedtls_ecp_point mP; /* mP value */
488 mbedtls_ecp_point R; /* R intermediate result */
489 enum { /* what should we do next? */
490 ecp_rsma_mul1 = 0, /* first multiplication */
491 ecp_rsma_mul2, /* second multiplication */
492 ecp_rsma_add, /* addition */
493 ecp_rsma_norm, /* normalization */
494 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200495};
496
497/*
498 * Init restart_muladd sub-context
499 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200500static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200501{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200502 mbedtls_ecp_point_init( &ctx->mP );
503 mbedtls_ecp_point_init( &ctx->R );
504 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200505}
506
507/*
508 * Free the components of a restart_muladd sub-context
509 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200510static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200511{
512 if( ctx == NULL )
513 return;
514
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200515 mbedtls_ecp_point_free( &ctx->mP );
516 mbedtls_ecp_point_free( &ctx->R );
517
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200518 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200519}
520
521/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200522 * Initialize a restart context
523 */
524void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
525{
Hanno Becker80f71682018-12-18 23:44:43 +0000526 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200527 ctx->ops_done = 0;
528 ctx->depth = 0;
529 ctx->rsm = NULL;
530 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200531}
532
533/*
534 * Free the components of a restart context
535 */
536void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
537{
538 if( ctx == NULL )
539 return;
540
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200541 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200542 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200543
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200544 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200545 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200546
547 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200548}
549
550/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100551 * Check if we can do the next step
552 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200553int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
554 mbedtls_ecp_restart_ctx *rs_ctx,
555 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100556{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000557 ECP_VALIDATE_RET( grp != NULL );
558
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200559 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100560 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100561 /* scale depending on curve size: the chosen reference is 256-bit,
562 * and multiplication is quadratic. Round to the closest integer. */
563 if( grp->pbits >= 512 )
564 ops *= 4;
565 else if( grp->pbits >= 384 )
566 ops *= 2;
567
Hanno Beckerb10c6602018-10-26 13:50:13 +0100568 /* Avoid infinite loops: always allow first step.
569 * Because of that, however, it's not generally true
570 * that ops_done <= ecp_max_ops, so the check
571 * ops_done > ecp_max_ops below is mandatory. */
572 if( ( rs_ctx->ops_done != 0 ) &&
573 ( rs_ctx->ops_done > ecp_max_ops ||
574 ops > ecp_max_ops - rs_ctx->ops_done ) )
575 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100576 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100577 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100578
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100579 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200580 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100581 }
582
583 return( 0 );
584}
585
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200586/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200587#define ECP_RS_ENTER( SUB ) do { \
588 /* reset ops count for this call if top-level */ \
589 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
590 rs_ctx->ops_done = 0; \
591 \
592 /* set up our own sub-context if needed */ \
593 if( mbedtls_ecp_restart_is_enabled() && \
594 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
595 { \
596 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
597 if( rs_ctx->SUB == NULL ) \
598 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
599 \
600 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
601 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200602} while( 0 )
603
604/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200605#define ECP_RS_LEAVE( SUB ) do { \
606 /* clear our sub-context when not in progress (done or error) */ \
607 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
608 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
609 { \
610 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
611 mbedtls_free( rs_ctx->SUB ); \
612 rs_ctx->SUB = NULL; \
613 } \
614 \
615 if( rs_ctx != NULL ) \
616 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200617} while( 0 )
618
619#else /* MBEDTLS_ECP_RESTARTABLE */
620
621#define ECP_RS_ENTER( sub ) (void) rs_ctx;
622#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
623
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200624#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
627 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
628 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
629 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
630 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
631 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
632 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
633 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
634 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
635 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
636 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200637#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100638#endif
639
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000640#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
641 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200642#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100643#endif
644
645/*
646 * Curve types: internal for now, might be exposed later
647 */
648typedef enum
649{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200650 ECP_TYPE_NONE = 0,
651 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
652 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100653} ecp_curve_type;
654
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100655/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200656 * List of supported curves:
657 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200658 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200659 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200660 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100661 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100662 * Curves are listed in order: largest curves first, and for a given size,
663 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200664 *
665 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200668{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
670 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200671#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
673 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100674#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
676 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200677#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
679 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100680#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
682 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200683#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
685 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100686#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
688 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100689#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
691 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200692#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
694 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100695#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
697 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100698#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
700 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100701#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200703};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100704
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200705#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
706 sizeof( ecp_supported_curves[0] )
707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200709
710/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200711 * List of supported curves and associated info
712 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200714{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200715 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200716}
717
718/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100719 * List of supported curves, group ID only
720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100722{
723 static int init_done = 0;
724
725 if( ! init_done )
726 {
727 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 for( curve_info = mbedtls_ecp_curve_list();
731 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100732 curve_info++ )
733 {
734 ecp_supported_grp_id[i++] = curve_info->grp_id;
735 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100737
738 init_done = 1;
739 }
740
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200741 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100742}
743
744/*
745 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747const 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 +0200748{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 for( curve_info = mbedtls_ecp_curve_list();
752 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200753 curve_info++ )
754 {
755 if( curve_info->grp_id == grp_id )
756 return( curve_info );
757 }
758
759 return( NULL );
760}
761
762/*
763 * Get the curve info from the TLS identifier
764 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200766{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200767 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 for( curve_info = mbedtls_ecp_curve_list();
770 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200771 curve_info++ )
772 {
773 if( curve_info->tls_id == tls_id )
774 return( curve_info );
775 }
776
777 return( NULL );
778}
779
780/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100781 * Get the curve info from the name
782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100784{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100786
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000787 if( name == NULL )
788 return( NULL );
789
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 for( curve_info = mbedtls_ecp_curve_list();
791 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100792 curve_info++ )
793 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200794 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100795 return( curve_info );
796 }
797
798 return( NULL );
799}
800
801/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100802 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100803 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100805{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100806 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200807 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100808
809 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200810 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100811 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200812 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100813}
814
815/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100816 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100817 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200818void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100819{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000820 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822 mbedtls_mpi_init( &pt->X );
823 mbedtls_mpi_init( &pt->Y );
824 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100825}
826
827/*
828 * Initialize (the components of) a group
829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200830void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100831{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000832 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100833
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200834 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200835 mbedtls_mpi_init( &grp->P );
836 mbedtls_mpi_init( &grp->A );
837 mbedtls_mpi_init( &grp->B );
838 mbedtls_ecp_point_init( &grp->G );
839 mbedtls_mpi_init( &grp->N );
840 grp->pbits = 0;
841 grp->nbits = 0;
842 grp->h = 0;
843 grp->modp = NULL;
844 grp->t_pre = NULL;
845 grp->t_post = NULL;
846 grp->t_data = NULL;
847 grp->T = NULL;
848 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100849}
850
851/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200852 * Initialize (the components of) a key pair
853 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200854void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200855{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000856 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 mbedtls_ecp_group_init( &key->grp );
859 mbedtls_mpi_init( &key->d );
860 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200861}
862
863/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100864 * Unallocate (the components of) a point
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100867{
868 if( pt == NULL )
869 return;
870
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 mbedtls_mpi_free( &( pt->X ) );
872 mbedtls_mpi_free( &( pt->Y ) );
873 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100874}
875
876/*
877 * Unallocate (the components of) a group
878 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100880{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200881 size_t i;
882
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100883 if( grp == NULL )
884 return;
885
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100886 if( grp->h != 1 )
887 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 mbedtls_mpi_free( &grp->P );
889 mbedtls_mpi_free( &grp->A );
890 mbedtls_mpi_free( &grp->B );
891 mbedtls_ecp_point_free( &grp->G );
892 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100893 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200894
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200895 if( grp->T != NULL )
896 {
897 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200898 mbedtls_ecp_point_free( &grp->T[i] );
899 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200900 }
901
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500902 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100903}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100904
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100905/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200906 * Unallocate (the components of) a key pair
907 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200909{
Paul Bakker66d5d072014-06-17 16:39:18 +0200910 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200911 return;
912
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200913 mbedtls_ecp_group_free( &key->grp );
914 mbedtls_mpi_free( &key->d );
915 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200916}
917
918/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200919 * Copy the contents of a point
920 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200922{
923 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000924 ECP_VALIDATE_RET( P != NULL );
925 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
928 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
929 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200930
931cleanup:
932 return( ret );
933}
934
935/*
936 * Copy the contents of a group object
937 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200939{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000940 ECP_VALIDATE_RET( dst != NULL );
941 ECP_VALIDATE_RET( src != NULL );
942
943 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200944}
945
946/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100947 * Set point to zero
948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100950{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100951 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000952 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
955 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
956 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100957
958cleanup:
959 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100960}
961
962/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100963 * Tell if a point is zero
964 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100966{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000967 ECP_VALIDATE_RET( pt != NULL );
968
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100970}
971
972/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700973 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200974 */
975int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
976 const mbedtls_ecp_point *Q )
977{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000978 ECP_VALIDATE_RET( P != NULL );
979 ECP_VALIDATE_RET( Q != NULL );
980
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200981 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
982 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
983 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
984 {
985 return( 0 );
986 }
987
988 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
989}
990
991/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100992 * Import a non-zero point from ASCII strings
993 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100995 const char *x, const char *y )
996{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100997 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000998 ECP_VALIDATE_RET( P != NULL );
999 ECP_VALIDATE_RET( x != NULL );
1000 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001001
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001002 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
1003 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
1004 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001005
1006cleanup:
1007 return( ret );
1008}
1009
1010/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001011 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001012 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001013int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
1014 const mbedtls_ecp_point *P,
1015 int format, size_t *olen,
1016 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001017{
Paul Bakkera280d0f2013-04-08 13:40:17 +02001018 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001019 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001020 ECP_VALIDATE_RET( grp != NULL );
1021 ECP_VALIDATE_RET( P != NULL );
1022 ECP_VALIDATE_RET( olen != NULL );
1023 ECP_VALIDATE_RET( buf != NULL );
1024 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1025 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001026
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001027 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001028 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001031 {
1032 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001034
1035 buf[0] = 0x00;
1036 *olen = 1;
1037
1038 return( 0 );
1039 }
1040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001043 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001044 {
1045 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001046
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001047 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001049
1050 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001051 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1052 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001053 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001054 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001055 {
1056 *olen = plen + 1;
1057
1058 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1062 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001063 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001064
1065cleanup:
1066 return( ret );
1067}
1068
1069/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001070 * Import a point from unsigned binary data (SEC1 2.3.4)
1071 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001072int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1073 mbedtls_ecp_point *pt,
1074 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001075{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001076 int ret;
1077 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001078 ECP_VALIDATE_RET( grp != NULL );
1079 ECP_VALIDATE_RET( pt != NULL );
1080 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001081
Paul Bakker82788fb2014-10-20 13:59:19 +02001082 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001084
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001085 if( buf[0] == 0x00 )
1086 {
1087 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001089 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001090 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001091 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001092
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001094
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001095 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001097
1098 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001099 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1102 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1103 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001104
1105cleanup:
1106 return( ret );
1107}
1108
1109/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001110 * Import a point from a TLS ECPoint record (RFC 4492)
1111 * struct {
1112 * opaque point <1..2^8-1>;
1113 * } ECPoint;
1114 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001115int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1116 mbedtls_ecp_point *pt,
1117 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001118{
1119 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001120 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001121 ECP_VALIDATE_RET( grp != NULL );
1122 ECP_VALIDATE_RET( pt != NULL );
1123 ECP_VALIDATE_RET( buf != NULL );
1124 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001125
1126 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001127 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001128 */
1129 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001130 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001131
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001132 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001133 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001135
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001136 /*
1137 * Save buffer start for read_binary and update buf
1138 */
1139 buf_start = *buf;
1140 *buf += data_len;
1141
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001142 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001143}
1144
1145/*
1146 * Export a point as a TLS ECPoint record (RFC 4492)
1147 * struct {
1148 * opaque point <1..2^8-1>;
1149 * } ECPoint;
1150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001151int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001152 int format, size_t *olen,
1153 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001154{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001155 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001156 ECP_VALIDATE_RET( grp != NULL );
1157 ECP_VALIDATE_RET( pt != NULL );
1158 ECP_VALIDATE_RET( olen != NULL );
1159 ECP_VALIDATE_RET( buf != NULL );
1160 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1161 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001162
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001163 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001164 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001165 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001166 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001170 olen, buf + 1, blen - 1) ) != 0 )
1171 return( ret );
1172
1173 /*
1174 * write length to the first byte and update total length
1175 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001176 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001177 ++*olen;
1178
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001179 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001180}
1181
1182/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001183 * Set a group from an ECParameters record (RFC 4492)
1184 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001185int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1186 const unsigned char **buf, size_t len )
1187{
1188 int ret;
1189 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001190 ECP_VALIDATE_RET( grp != NULL );
1191 ECP_VALIDATE_RET( buf != NULL );
1192 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001193
1194 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1195 return( ret );
1196
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001197 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001198}
1199
1200/*
1201 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1202 * mbedtls_ecp_group_id.
1203 */
1204int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1205 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001206{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001207 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001208 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001209 ECP_VALIDATE_RET( grp != NULL );
1210 ECP_VALIDATE_RET( buf != NULL );
1211 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001212
1213 /*
1214 * We expect at least three bytes (see below)
1215 */
1216 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001217 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001218
1219 /*
1220 * First byte is curve_type; only named_curve is handled
1221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001222 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1223 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001224
1225 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001226 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001227 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001228 tls_id = *(*buf)++;
1229 tls_id <<= 8;
1230 tls_id |= *(*buf)++;
1231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001232 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1233 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001234
Janos Follath89ac8c92018-10-30 11:24:05 +00001235 *grp = curve_info->grp_id;
1236
1237 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001238}
1239
1240/*
1241 * Write the ECParameters record corresponding to a group (RFC 4492)
1242 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001243int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001244 unsigned char *buf, size_t blen )
1245{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001246 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001247 ECP_VALIDATE_RET( grp != NULL );
1248 ECP_VALIDATE_RET( buf != NULL );
1249 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001251 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1252 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001253
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001254 /*
1255 * We are going to write 3 bytes (see below)
1256 */
1257 *olen = 3;
1258 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001259 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001260
1261 /*
1262 * First byte is curve_type, always named_curve
1263 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001265
1266 /*
1267 * Next two bytes are the namedcurve value
1268 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001269 buf[0] = curve_info->tls_id >> 8;
1270 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001271
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001272 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001273}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001274
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001275/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1277 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001278 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001279 * 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 +02001280 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001282{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001283 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001284
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001285 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001287
1288 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001290 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001291 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001293 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001296
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001297 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1299 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001302 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001304
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001305cleanup:
1306 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001307}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001308
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001309/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001310 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001311 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001312 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001313 * 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 +01001314 * bring the result back to this range.
1315 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001316 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001317 */
1318
1319/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001320 * 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 +01001321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001323#define INC_MUL_COUNT mul_count++;
1324#else
1325#define INC_MUL_COUNT
1326#endif
1327
Hanno Beckerd6028a12018-10-15 12:01:35 +01001328#define MOD_MUL( N ) \
1329 do \
1330 { \
1331 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1332 INC_MUL_COUNT \
1333 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001334
1335/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001337 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001338 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001339#define MOD_SUB( N ) \
1340 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1341 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001342
1343/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 * 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 +02001345 * We known P, N and the result are positive, so sub_abs is correct, and
1346 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001347 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001348#define MOD_ADD( N ) \
1349 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001351
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001352#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001353/*
1354 * For curves in short Weierstrass form, we do all the internal operations in
1355 * Jacobian coordinates.
1356 *
1357 * For multiplication, we'll use a comb method with coutermeasueres against
1358 * SPA, hence timing attacks.
1359 */
1360
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001361/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001362 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001363 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001366{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001367 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001371 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001372
Janos Follathb0697532016-08-18 12:38:46 +01001373#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001374 if( mbedtls_internal_ecp_grp_capable( grp ) )
1375 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001376#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001377
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001379
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001380 /*
1381 * X = X / Z^2 mod p
1382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1384 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1385 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 +01001386
1387 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001388 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001389 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001390 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1391 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 +01001392
1393 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001394 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001395 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001397
1398cleanup:
1399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001400 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001401
1402 return( ret );
1403}
1404
1405/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001406 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001407 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001408 * (See for example Cohen's "A Course in Computational Algebraic Number
1409 * Theory", Algorithm 10.3.4.)
1410 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001411 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001412 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001413 *
1414 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001417 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001418{
1419 int ret;
1420 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001421 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001422
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001423 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001424 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001425
Janos Follathb0697532016-08-18 12:38:46 +01001426#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001427 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001428 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001429#endif
1430
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001431 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001432 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001433
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001434 for( i = 0; i < T_size; i++ )
1435 mbedtls_mpi_init( &c[i] );
1436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001438
1439 /*
1440 * c[i] = Z_0 * ... * Z_i
1441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001443 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001444 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001446 MOD_MUL( c[i] );
1447 }
1448
1449 /*
1450 * u = 1 / (Z_0 * ... * Z_n) mod P
1451 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001452 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001453
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001454 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001455 {
1456 /*
1457 * Zi = 1 / Z_i mod p
1458 * u = 1 / (Z_0 * ... * Z_i) mod P
1459 */
1460 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001462 }
1463 else
1464 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001465 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1466 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001467 }
1468
1469 /*
1470 * proceed as in normalize()
1471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001472 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1474 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1475 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 +01001476
1477 /*
1478 * Post-precessing: reclaim some memory by shrinking coordinates
1479 * - not storing Z (always 1)
1480 * - shrinking other coordinates, but still keeping the same number of
1481 * limbs as P, as otherwise it will too likely be regrown too fast.
1482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001483 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1484 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1485 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001486
1487 if( i == 0 )
1488 break;
1489 }
1490
1491cleanup:
1492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001493 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001494 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001495 mbedtls_mpi_free( &c[i] );
1496 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001497
1498 return( ret );
1499}
1500
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001501/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001502 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1503 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1504 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1506 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001507 unsigned char inv )
1508{
1509 int ret;
1510 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001514
1515 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1517 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1518 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001519
1520cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001522
1523 return( ret );
1524}
1525
1526/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001527 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001528 *
Peter Dettmance661b22015-02-07 14:43:51 +07001529 * 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 +01001530 *
Peter Dettmance661b22015-02-07 14:43:51 +07001531 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1532 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1533 *
1534 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1535 *
1536 * Cost: 1D := 3M + 4S (A == 0)
1537 * 4M + 4S (A == -3)
1538 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001539 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1541 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001542{
1543 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001544 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001547 dbl_count++;
1548#endif
1549
Janos Follathb0697532016-08-18 12:38:46 +01001550#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001551 if( mbedtls_internal_ecp_grp_capable( grp ) )
1552 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001553#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001554
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001555 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 +01001556
1557 /* Special case for A = -3 */
1558 if( grp->A.p == NULL )
1559 {
Peter Dettmance661b22015-02-07 14:43:51 +07001560 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001561 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1562 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1564 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001566 }
1567 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001568 {
Peter Dettmance661b22015-02-07 14:43:51 +07001569 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001570 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001572
1573 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001574 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001575 {
1576 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1578 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001581 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001582 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001583
Peter Dettmance661b22015-02-07 14:43:51 +07001584 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001585 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1586 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001589
Peter Dettmance661b22015-02-07 14:43:51 +07001590 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001591 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1592 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001593
1594 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001595 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1596 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1597 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001598
1599 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001600 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1601 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1602 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001603
1604 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001605 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1606 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001607
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001608 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1610 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001611
1612cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001613 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 +02001614
1615 return( ret );
1616}
1617
1618/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001619 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001620 *
1621 * The coordinates of Q must be normalized (= affine),
1622 * but those of P don't need to. R is not normalized.
1623 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001624 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001625 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001626 * - at each step, P, Q and R are multiples of the base point, the factor
1627 * being less than its order, so none of them is zero;
1628 * - Q is an odd multiple of the base point, P an even multiple,
1629 * due to the choice of precomputed points in the modified comb method.
1630 * So branches for these cases do not leak secret information.
1631 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001632 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1633 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001634 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1637 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001638{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001639 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001642#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001643 add_count++;
1644#endif
1645
Janos Follathb0697532016-08-18 12:38:46 +01001646#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001647 if( mbedtls_internal_ecp_grp_capable( grp ) )
1648 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001649#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001650
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001651 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001652 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1655 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1658 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001659
1660 /*
1661 * Make sure Q coordinates are normalized
1662 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1664 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1667 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001668
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001669 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1670 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001675
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001676 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001678 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001679 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001680 {
1681 ret = ecp_double_jac( grp, R, P );
1682 goto cleanup;
1683 }
1684 else
1685 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001687 goto cleanup;
1688 }
1689 }
1690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001691 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1692 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1699 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1700 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1701 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1702 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001707
1708cleanup:
1709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001710 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1711 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001712
1713 return( ret );
1714}
1715
1716/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001717 * Randomize jacobian coordinates:
1718 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001719 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001720 *
1721 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001722 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001724 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1725{
1726 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001728 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001729 int count = 0;
1730
Janos Follathb0697532016-08-18 12:38:46 +01001731#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001732 if( mbedtls_internal_ecp_grp_capable( grp ) )
1733 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001734#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001735
1736 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001737 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001738
1739 /* Generate l such that 1 < l < p */
1740 do
1741 {
Ronald Cron2e0969a2021-06-10 17:24:02 +02001742 if( count++ > 30 )
Jonas6645fd32020-05-08 16:57:18 +09001743 {
1744 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1745 goto cleanup;
1746 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02001747
1748 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
1749 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001750 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02001751 while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
1752 ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001753
1754 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755 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 +02001756
1757 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1759 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 +02001760
1761 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1763 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 +02001764
1765cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001766 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001767
1768 return( ret );
1769}
1770
1771/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001772 * Check and define parameters used by the comb method (see below for details)
1773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1775#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001776#endif
1777
1778/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001779#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001780
1781/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001782#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001783
1784/*
1785 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001786 *
1787 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001788 * modified version that provides resistance to SPA by avoiding zero
1789 * digits in the representation as in [3]. We modify the method further by
1790 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001791 * representation uses one more K_i, due to carries, but saves on the size of
1792 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001793 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001794 * Summary of the comb method and its modifications:
1795 *
1796 * - The goal is to compute m*P for some w*d-bit integer m.
1797 *
1798 * - The basic comb method splits m into the w-bit integers
1799 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1800 * index has residue i modulo d, and computes m * P as
1801 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1802 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1803 *
1804 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1805 * .. + 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]] ..,
1806 * thereby successively converting it into a form where all summands
1807 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1808 *
1809 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1810 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1811 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1812 * Performing and iterating this procedure for those x[i] that are even
1813 * (keeping track of carry), we can transform the original sum into one of the form
1814 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1815 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1816 * which is why we are only computing half of it in the first place in
1817 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1818 *
1819 * - For the sake of compactness, only the seven low-order bits of x[i]
1820 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001821 * 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 +02001822 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001823 *
1824 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001825 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001826 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001827 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001828 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1829 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001830 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001831static void ecp_comb_recode_core( unsigned char x[], size_t d,
1832 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001833{
1834 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001835 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001836
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001837 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001838
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001839 /* First get the classical comb values (except for x_d = 0) */
1840 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001841 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001842 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001843
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001844 /* Now make sure x_1 .. x_d are odd */
1845 c = 0;
1846 for( i = 1; i <= d; i++ )
1847 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001848 /* Add carry and update it */
1849 cc = x[i] & c;
1850 x[i] = x[i] ^ c;
1851 c = cc;
1852
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001853 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001854 adjust = 1 - ( x[i] & 0x01 );
1855 c |= x[i] & ( x[i-1] * adjust );
1856 x[i] = x[i] ^ ( x[i-1] * adjust );
1857 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001858 }
1859}
1860
1861/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001862 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001863 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001864 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001865 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001866 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1867 * 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 +01001868 *
1869 * 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 +02001870 *
1871 * Note: Even comb values (those where P would be omitted from the
1872 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001873 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001874 *
1875 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001876 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001877 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1878 * (3) [add] Computation of all T[i]
1879 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001880 *
1881 * Step 1 can be interrupted but not the others; together with the final
1882 * coordinate normalization they are the largest steps done at once, depending
1883 * on the window size. Here are operation counts for P-256:
1884 *
1885 * step (2) (3) (4)
1886 * w = 5 142 165 208
1887 * w = 4 136 77 160
1888 * w = 3 130 33 136
1889 * w = 2 124 11 124
1890 *
1891 * So if ECC operations are blocking for too long even with a low max_ops
1892 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1893 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001894 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1896 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001897 unsigned char w, size_t d,
1898 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001899{
1900 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001901 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001902 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001903 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001905
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001906#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001907 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001908 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001909 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1910 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001911 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001912 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001913 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1914 goto add;
1915 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1916 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001917 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001918#else
1919 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001920#endif
1921
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001922#if defined(MBEDTLS_ECP_RESTARTABLE)
1923 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1924 {
1925 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1926
1927 /* initial state for the loop */
1928 rs_ctx->rsm->i = 0;
1929 }
1930
1931dbl:
1932#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001933 /*
1934 * Set T[0] = P and
1935 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1936 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001937 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001938
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001939#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001940 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1941 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001942 else
1943#endif
1944 j = 0;
1945
1946 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001947 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001948 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001949
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001950 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001951 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001952
1953 if( j % d == 0 )
1954 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1955
1956 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001957 }
1958
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001959#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001960 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1961 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1962
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001963norm_dbl:
1964#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001965 /*
1966 * Normalize current elements in T. As T has holes,
1967 * use an auxiliary array of pointers to elements in T.
1968 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001969 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001970 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001971 TT[j++] = T + i;
1972
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001973 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001974
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001975 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001976
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001977#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001978 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1979 rs_ctx->rsm->state = ecp_rsm_pre_add;
1980
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001981add:
1982#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001983 /*
1984 * Compute the remaining ones using the minimal number of additions
1985 * Be careful to update T[2^l] only after using it!
1986 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001987 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001988
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001989 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001990 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001991 j = i;
1992 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001993 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001994 }
1995
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001996#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001997 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1998 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
1999
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01002000norm_add:
2001#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002002 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02002003 * Normalize final elements in T. Even though there are no holes now, we
2004 * still need the auxiliary array for homogeneity with the previous
2005 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002006 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002007 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002008 TT[j] = T + j + 1;
2009
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002010 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01002011
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002012 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01002013
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002014cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002015#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002016 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2017 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002018 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002019 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002020 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002021 }
2022#endif
Janos Follathb0697532016-08-18 12:38:46 +01002023
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002024 return( ret );
2025}
2026
2027/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002028 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002029 *
2030 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002031 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002033 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002034 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002035{
2036 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002037 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002038
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002039 /* Ignore the "sign" bit and scale down */
2040 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002041
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002042 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002043 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002044 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2046 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002047 }
2048
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002049 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002050 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002051
2052cleanup:
2053 return( ret );
2054}
2055
2056/*
2057 * Core multiplication algorithm for the (modified) comb method.
2058 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002059 *
2060 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002063 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002064 const unsigned char x[], size_t d,
2065 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002066 void *p_rng,
2067 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002068{
2069 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002071 size_t i;
2072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002074
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002075#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002076 (void) rs_ctx;
2077#endif
2078
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002079#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002080 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2081 rs_ctx->rsm->state != ecp_rsm_comb_core )
2082 {
2083 rs_ctx->rsm->i = 0;
2084 rs_ctx->rsm->state = ecp_rsm_comb_core;
2085 }
2086
2087 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002088 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002089 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002090 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2091 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002092 }
2093 else
2094#endif
2095 {
2096 /* Start with a non-zero point and randomize its coordinates */
2097 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002098 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002099 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002100#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002101 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002102#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002103 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2104 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002105
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002106 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002107 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002108 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002109 --i;
2110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002111 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002112 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002114 }
2115
2116cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002117
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002118 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002119
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002120#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002121 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2122 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002123 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002124 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002125 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002126 }
2127#endif
2128
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002129 return( ret );
2130}
2131
2132/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002133 * Recode the scalar to get constant-time comb multiplication
2134 *
2135 * As the actual scalar recoding needs an odd scalar as a starting point,
2136 * this wrapper ensures that by replacing m by N - m if necessary, and
2137 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002138 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002139 * This works because we only support large prime order for Short Weierstrass
2140 * curves, so N is always odd hence either m or N - m is.
2141 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002142 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002143 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002144static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2145 const mbedtls_mpi *m,
2146 unsigned char k[COMB_MAX_D + 1],
2147 size_t d,
2148 unsigned char w,
2149 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002150{
2151 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002152 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002153
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002154 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002155 mbedtls_mpi_init( &mm );
2156
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002157 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002158 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2159 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2160
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002161 /* do we need the parity trick? */
2162 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2163
2164 /* execute parity fix in constant time */
2165 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002166 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002167 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2168
2169 /* actual scalar recoding */
2170 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002171
2172cleanup:
2173 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002174 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002175
2176 return( ret );
2177}
2178
2179/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002180 * Perform comb multiplication (for short Weierstrass curves)
2181 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002182 *
2183 * Scalar recoding may use a parity trick that makes us compute -m * P,
2184 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002185 */
2186static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2187 mbedtls_ecp_point *R,
2188 const mbedtls_mpi *m,
2189 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002190 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002191 unsigned char w,
2192 size_t d,
2193 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002194 void *p_rng,
2195 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002196{
2197 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002198 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002199 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002200 mbedtls_ecp_point *RR = R;
2201
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002202#if defined(MBEDTLS_ECP_RESTARTABLE)
2203 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2204 {
2205 RR = &rs_ctx->rsm->R;
2206
2207 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2208 goto final_norm;
2209 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002210#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002211
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002212 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2213 &parity_trick ) );
2214 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2215 f_rng, p_rng, rs_ctx ) );
2216 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2217
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002218#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002219 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002220 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002221
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002222final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002223 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002224#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002225 /*
2226 * Knowledge of the jacobian coordinates may leak the last few bits of the
2227 * scalar [1], and since our MPI implementation isn't constant-flow,
2228 * inversion (used for coordinate normalization) may leak the full value
2229 * of its input via side-channels [2].
2230 *
2231 * [1] https://eprint.iacr.org/2003/191
2232 * [2] https://eprint.iacr.org/2020/055
2233 *
2234 * Avoid the leak by randomizing coordinates before we normalize them.
2235 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002236#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002237 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002238#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002239 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2240
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002241 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2242
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002243#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002244 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2245 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002246#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002247
2248cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002249 return( ret );
2250}
2251
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002252/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002253 * Pick window size based on curve size and whether we optimize for base point
2254 */
2255static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2256 unsigned char p_eq_g )
2257{
2258 unsigned char w;
2259
2260 /*
2261 * Minimize the number of multiplications, that is minimize
2262 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2263 * (see costs of the various parts, with 1S = 1M)
2264 */
2265 w = grp->nbits >= 384 ? 5 : 4;
2266
2267 /*
2268 * If P == G, pre-compute a bit more, since this may be re-used later.
2269 * Just adding one avoids upping the cost of the first mul too much,
2270 * and the memory cost too.
2271 */
2272 if( p_eq_g )
2273 w++;
2274
2275 /*
2276 * Make sure w is within bounds.
2277 * (The last test is useful only for very small curves in the test suite.)
2278 */
2279 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2280 w = MBEDTLS_ECP_WINDOW_SIZE;
2281 if( w >= grp->nbits )
2282 w = 2;
2283
2284 return( w );
2285}
2286
2287/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002288 * Multiplication using the comb method - for curves in short Weierstrass form
2289 *
2290 * This function is mainly responsible for administrative work:
2291 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002292 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002293 * functions): allocation, computation, ownership tranfer, freeing.
2294 *
2295 * It delegates the actual arithmetic work to:
2296 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2297 *
2298 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002300static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2301 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002302 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002303 void *p_rng,
2304 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002305{
2306 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002307 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002308 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002309 unsigned char T_size = 0, T_ok = 0;
2310 mbedtls_ecp_point *T = NULL;
2311#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2312 ecp_drbg_context drbg_ctx;
2313
2314 ecp_drbg_init( &drbg_ctx );
2315#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002316
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002317 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002318
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002319#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2320 if( f_rng == NULL )
2321 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002322 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002323 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002324#if defined(MBEDTLS_ECP_RESTARTABLE)
2325 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2326 p_rng = &rs_ctx->rsm->drbg_ctx;
2327 else
2328#endif
2329 p_rng = &drbg_ctx;
2330
2331 /* Initialize internal DRBG if necessary */
2332#if defined(MBEDTLS_ECP_RESTARTABLE)
2333 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2334 rs_ctx->rsm->drbg_seeded == 0 )
2335#endif
2336 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002337 const size_t m_len = ( grp->nbits + 7 ) / 8;
2338 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002339 }
2340#if defined(MBEDTLS_ECP_RESTARTABLE)
2341 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2342 rs_ctx->rsm->drbg_seeded = 1;
2343#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002344 }
2345#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2346
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002347 /* Is P the base point ? */
2348#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2349 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2350 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002351#else
2352 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002353#endif
2354
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002355 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002356 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002357 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002358 d = ( grp->nbits + w - 1 ) / w;
2359
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002360 /* Pre-computed table: do we have it already for the base point? */
2361 if( p_eq_g && grp->T != NULL )
2362 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002363 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002364 T = grp->T;
2365 T_ok = 1;
2366 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002367 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002368#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002369 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002370 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002371 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002372 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002373 T = rs_ctx->rsm->T;
2374 rs_ctx->rsm->T = NULL;
2375 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002376
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002377 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002378 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002379 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002380 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002381#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002382 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002383 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002384 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002385 if( T == NULL )
2386 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002387 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002388 goto cleanup;
2389 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002390
2391 for( i = 0; i < T_size; i++ )
2392 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002393
2394 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002395 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002396
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002397 /* Compute table (or finish computing it) if not done already */
2398 if( !T_ok )
2399 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002400 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002401
2402 if( p_eq_g )
2403 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002404 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002405 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002406 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002407 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002408 }
2409 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002410
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002411 /* Actual comb multiplication using precomputed points */
2412 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002413 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002414 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002415
2416cleanup:
2417
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002418#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2419 ecp_drbg_free( &drbg_ctx );
2420#endif
2421
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002422 /* does T belong to the group? */
2423 if( T == grp->T )
2424 T = NULL;
2425
2426 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002427#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002428 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 +01002429 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002430 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002431 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002432 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002433 T = NULL;
2434 }
2435#endif
2436
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002437 /* did T belong to us? then let's destroy it! */
2438 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002439 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002440 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002441 mbedtls_ecp_point_free( &T[i] );
2442 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002443 }
2444
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002445 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002446#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002447 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2448#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002449 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002450 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002451 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002452
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002453 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002454
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002455 return( ret );
2456}
2457
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002458#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002459
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002460#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002461/*
2462 * For Montgomery curves, we do all the internal arithmetic in projective
2463 * coordinates. Import/export of points uses only the x coordinates, which is
2464 * internaly represented as X / Z.
2465 *
2466 * For scalar multiplication, we'll use a Montgomery ladder.
2467 */
2468
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002469/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002470 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2471 * Cost: 1M + 1I
2472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002474{
2475 int ret;
2476
Janos Follathb0697532016-08-18 12:38:46 +01002477#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002478 if( mbedtls_internal_ecp_grp_capable( grp ) )
2479 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002480#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002482 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2483 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2484 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002485
2486cleanup:
2487 return( ret );
2488}
2489
2490/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002491 * Randomize projective x/z coordinates:
2492 * (X, Z) -> (l X, l Z) for random l
2493 * This is sort of the reverse operation of ecp_normalize_mxz().
2494 *
2495 * This countermeasure was first suggested in [2].
2496 * Cost: 2M
2497 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002499 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2500{
2501 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002502 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002503 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002504 int count = 0;
2505
Janos Follathb0697532016-08-18 12:38:46 +01002506#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002507 if( mbedtls_internal_ecp_grp_capable( grp ) )
Steven Cooreman4a5ed022021-03-11 13:18:29 +01002508 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01002509#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002510
2511 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002513
2514 /* Generate l such that 1 < l < p */
2515 do
2516 {
Ronald Cron2e0969a2021-06-10 17:24:02 +02002517 if( count++ > 30 )
Jonas6645fd32020-05-08 16:57:18 +09002518 {
2519 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2520 goto cleanup;
2521 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02002522
2523 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
2524 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, ( p_size * 8 ) - grp->pbits ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002525 }
Ronald Cron2e0969a2021-06-10 17:24:02 +02002526 while( ( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ) ||
2527 ( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2530 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 +01002531
2532cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002533 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002534
2535 return( ret );
2536}
2537
2538/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002539 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2540 * for Montgomery curves in x/z coordinates.
2541 *
2542 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2543 * with
2544 * d = X1
2545 * P = (X2, Z2)
2546 * Q = (X3, Z3)
2547 * R = (X4, Z4)
2548 * S = (X5, Z5)
2549 * and eliminating temporary variables tO, ..., t4.
2550 *
2551 * Cost: 5M + 4S
2552 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2554 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2555 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2556 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002557{
2558 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002560
Janos Follathb0697532016-08-18 12:38:46 +01002561#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002562 if( mbedtls_internal_ecp_grp_capable( grp ) )
2563 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002564#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2567 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2568 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002570 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2571 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2572 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2573 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2574 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2576 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2578 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2579 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2580 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2581 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2582 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2584 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2585 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2586 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2587 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 +01002588
2589cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2591 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2592 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002593
2594 return( ret );
2595}
2596
2597/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002598 * Multiplication with Montgomery ladder in x/z coordinates,
2599 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002600 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002601static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2602 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002603 int (*f_rng)(void *, unsigned char *, size_t),
2604 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002605{
2606 int ret;
2607 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002608 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002609 mbedtls_ecp_point RP;
2610 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002611#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2612 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002613
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002614 ecp_drbg_init( &drbg_ctx );
2615#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002617
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002618#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2619 if( f_rng == NULL )
2620 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002621 const size_t m_len = ( grp->nbits + 7 ) / 8;
2622 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002623 f_rng = &ecp_drbg_random;
2624 p_rng = &drbg_ctx;
2625 }
2626#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2627
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002628 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2630 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002631
2632 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2634 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2635 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002636
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002637 /* RP.X might be sligtly larger than P, so reduce it */
2638 MOD_ADD( RP.X );
2639
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002640 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002641#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002642 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002643#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002644 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002645
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002646 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002647 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002648 while( i-- > 0 )
2649 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002650 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002651 /*
2652 * if (b) R = 2R + P else R = 2R,
2653 * which is:
2654 * if (b) double_add( RP, R, RP, R )
2655 * else double_add( R, RP, R, RP )
2656 * but using safe conditional swaps to avoid leaks
2657 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002658 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2659 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
2660 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2661 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2662 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002663 }
2664
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002665 /*
2666 * Knowledge of the projective coordinates may leak the last few bits of the
2667 * scalar [1], and since our MPI implementation isn't constant-flow,
2668 * inversion (used for coordinate normalization) may leak the full value
2669 * of its input via side-channels [2].
2670 *
2671 * [1] https://eprint.iacr.org/2003/191
2672 * [2] https://eprint.iacr.org/2020/055
2673 *
2674 * Avoid the leak by randomizing coordinates before we normalize them.
2675 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002676#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002677 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002678#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002679 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002681 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002682
2683cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002684#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2685 ecp_drbg_free( &drbg_ctx );
2686#endif
2687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002688 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002689
2690 return( ret );
2691}
2692
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002693#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002694
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002695/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002696 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002697 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002698int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002699 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002700 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2701 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002702{
Janos Follathb0697532016-08-18 12:38:46 +01002703 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002704#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2705 char is_grp_capable = 0;
2706#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002707 ECP_VALIDATE_RET( grp != NULL );
2708 ECP_VALIDATE_RET( R != NULL );
2709 ECP_VALIDATE_RET( m != NULL );
2710 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002711
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002712#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002713 /* reset ops count for this call if top-level */
2714 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2715 rs_ctx->ops_done = 0;
2716#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002717
Janos Follathc44ab972016-11-18 16:38:23 +00002718#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002719 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002720 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002721#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002722
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002723#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002724 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002725 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002726#endif
2727 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002728 /* check_privkey is free */
2729 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2730
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002731 /* Common sanity checks */
2732 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2733 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002734 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002735
2736 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002737#if defined(ECP_MONTGOMERY)
2738 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002739 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002740#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002741#if defined(ECP_SHORTWEIERSTRASS)
2742 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002743 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002744#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002745
Janos Follath6c8ccd52016-11-29 15:37:09 +00002746cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002747
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002748#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002749 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002750 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002751#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002752
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002753#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002754 if( rs_ctx != NULL )
2755 rs_ctx->depth--;
2756#endif
2757
Janos Follathb0697532016-08-18 12:38:46 +01002758 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002759}
2760
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002761/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002762 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002763 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002764int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002765 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002766 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002767{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002768 ECP_VALIDATE_RET( grp != NULL );
2769 ECP_VALIDATE_RET( R != NULL );
2770 ECP_VALIDATE_RET( m != NULL );
2771 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002772 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002773}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002774
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002775#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002776/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002777 * Check that an affine point is valid as a public key,
2778 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002779 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002780static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002781{
2782 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002784
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002785 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2787 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2788 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2789 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2790 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002791
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002792 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002793
2794 /*
2795 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002796 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002797 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002798 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2799 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002800
2801 /* Special case for A = -3 */
2802 if( grp->A.p == NULL )
2803 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002804 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002805 }
2806 else
2807 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002808 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002809 }
2810
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2812 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2815 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002816
2817cleanup:
2818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002819 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002820
2821 return( ret );
2822}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002823#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002824
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002825/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002826 * R = m * P with shortcuts for m == 1 and m == -1
2827 * NOT constant-time - ONLY for short Weierstrass!
2828 */
2829static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2830 mbedtls_ecp_point *R,
2831 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002832 const mbedtls_ecp_point *P,
2833 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002834{
2835 int ret;
2836
2837 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2838 {
2839 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2840 }
2841 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2842 {
2843 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2844 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2845 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2846 }
2847 else
2848 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002849 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2850 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002851 }
2852
2853cleanup:
2854 return( ret );
2855}
2856
2857/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002858 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002859 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002860 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002861int mbedtls_ecp_muladd_restartable(
2862 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002863 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002864 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2865 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002866{
2867 int ret;
2868 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002869 mbedtls_ecp_point *pmP = &mP;
2870 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002871#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2872 char is_grp_capable = 0;
2873#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002874 ECP_VALIDATE_RET( grp != NULL );
2875 ECP_VALIDATE_RET( R != NULL );
2876 ECP_VALIDATE_RET( m != NULL );
2877 ECP_VALIDATE_RET( P != NULL );
2878 ECP_VALIDATE_RET( n != NULL );
2879 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002880
2881 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2882 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2883
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002884 mbedtls_ecp_point_init( &mP );
2885
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002886 ECP_RS_ENTER( ma );
2887
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002888#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002889 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2890 {
2891 /* redirect intermediate results to restart context */
2892 pmP = &rs_ctx->ma->mP;
2893 pR = &rs_ctx->ma->R;
2894
2895 /* jump to next operation */
2896 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2897 goto mul2;
2898 if( rs_ctx->ma->state == ecp_rsma_add )
2899 goto add;
2900 if( rs_ctx->ma->state == ecp_rsma_norm )
2901 goto norm;
2902 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002903#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002904
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002905 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002906#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002907 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002908 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002909
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002910mul2:
2911#endif
2912 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002913
2914#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2915 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2916 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2917#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2918
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002919#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002920 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002921 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002922
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002923add:
2924#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002925 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002926 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002927#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002928 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002929 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002930
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002931norm:
2932#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002933 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002934 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2935
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002936#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002937 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2938 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2939#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002940
2941cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002942#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002943 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002944 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002945#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002946
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002947 mbedtls_ecp_point_free( &mP );
2948
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002949 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002950
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002951 return( ret );
2952}
2953
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002954/*
2955 * Linear combination
2956 * NOT constant-time
2957 */
2958int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2959 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2960 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2961{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002962 ECP_VALIDATE_RET( grp != NULL );
2963 ECP_VALIDATE_RET( R != NULL );
2964 ECP_VALIDATE_RET( m != NULL );
2965 ECP_VALIDATE_RET( P != NULL );
2966 ECP_VALIDATE_RET( n != NULL );
2967 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002968 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2969}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002970
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002971#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02002972#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02002973#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)}
2974#define ECP_MPI_INIT_ARRAY(x) \
2975 ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
2976/*
2977 * Constants for the two points other than 0, 1, -1 (mod p) in
2978 * https://cr.yp.to/ecdh.html#validate
2979 * See ecp_check_pubkey_x25519().
2980 */
2981static const mbedtls_mpi_uint x25519_bad_point_1[] = {
Janos Follath9a64d3e2021-06-25 12:43:26 +01002982 MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ),
2983 MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ),
2984 MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ),
2985 MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ),
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02002986};
2987static const mbedtls_mpi_uint x25519_bad_point_2[] = {
Janos Follath9a64d3e2021-06-25 12:43:26 +01002988 MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ),
2989 MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ),
2990 MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ),
2991 MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ),
Manuel Pégourié-Gonnard9f12b112021-06-23 12:53:18 +02002992};
2993static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY(
2994 x25519_bad_point_1 );
2995static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY(
2996 x25519_bad_point_2 );
Janos Follath5f9b6672021-06-24 15:34:59 +01002997#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02002998
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02002999/*
3000 * Check that the input point is not one of the low-order points.
3001 * This is recommended by the "May the Fourth" paper:
3002 * https://eprint.iacr.org/2017/806.pdf
3003 * Those points are never sent by an honest peer.
3004 */
Janos Follath5f9b6672021-06-24 15:34:59 +01003005static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P,
3006 const mbedtls_ecp_group_id grp_id )
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003007{
3008 int ret;
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02003009 mbedtls_mpi XmP;
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003010
3011 mbedtls_mpi_init( &XmP );
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003012
3013 /* Reduce X mod P so that we only need to check values less than P.
3014 * We know X < 2^256 so we can proceed by subtraction. */
3015 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) );
3016 while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 )
3017 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) );
3018
Janos Follath5f9b6672021-06-24 15:34:59 +01003019 /* Check against the known bad values that are less than P. For Curve448
3020 * these are 0, 1 and -1. For Curve25519 we check the values less than P
3021 * from the following list: https://cr.yp.to/ecdh.html#validate */
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003022 if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */
Janos Follathc16ec6b2021-06-24 14:24:13 +01003023 {
3024 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
3025 goto cleanup;
3026 }
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003027
Janos Follath5f9b6672021-06-24 15:34:59 +01003028#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
3029 if( grp_id == MBEDTLS_ECP_DP_CURVE25519 )
Janos Follathc16ec6b2021-06-24 14:24:13 +01003030 {
Janos Follath5f9b6672021-06-24 15:34:59 +01003031 if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 )
3032 {
3033 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
3034 goto cleanup;
3035 }
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003036
Janos Follath5f9b6672021-06-24 15:34:59 +01003037 if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 )
3038 {
3039 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
3040 goto cleanup;
3041 }
Janos Follathc16ec6b2021-06-24 14:24:13 +01003042 }
Janos Follath1001d2c2021-06-25 15:29:56 +01003043#else
3044 (void) grp_id;
Janos Follath5f9b6672021-06-24 15:34:59 +01003045#endif
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003046
Manuel Pégourié-Gonnard6ec15352021-06-23 12:25:48 +02003047 /* Final check: check if XmP + 1 is P (final because it changes XmP!) */
3048 MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) );
3049 if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 )
Janos Follathc16ec6b2021-06-24 14:24:13 +01003050 {
3051 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
3052 goto cleanup;
3053 }
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003054
3055 ret = 0;
3056
3057cleanup:
3058 mbedtls_mpi_free( &XmP );
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003059
3060 return( ret );
3061}
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003062
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003063/*
3064 * Check validity of a public key for Montgomery curves with x-only schemes
3065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003066static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003067{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02003068 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003069 /* Allow any public value, if it's too big then we'll just reduce it mod p
3070 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003071 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
3072 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003073
Manuel Pégourié-Gonnard4d0b9da2021-06-23 10:14:58 +02003074 /* Implicit in all standards (as they don't consider negative numbers):
3075 * X must be non-negative. This is normally ensured by the way it's
3076 * encoded for transmission, but let's be extra sure. */
3077 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 )
3078 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3079
Janos Follath5f9b6672021-06-24 15:34:59 +01003080 return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003081}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003082#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003083
3084/*
3085 * Check that a point is valid as a public key
3086 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003087int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
3088 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003089{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003090 ECP_VALIDATE_RET( grp != NULL );
3091 ECP_VALIDATE_RET( pt != NULL );
3092
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003093 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003094 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
3095 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003096
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003097#if defined(ECP_MONTGOMERY)
3098 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003099 return( ecp_check_pubkey_mx( grp, pt ) );
3100#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003101#if defined(ECP_SHORTWEIERSTRASS)
3102 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003103 return( ecp_check_pubkey_sw( grp, pt ) );
3104#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003105 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003106}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003107
3108/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003109 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003110 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003111int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
3112 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003113{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003114 ECP_VALIDATE_RET( grp != NULL );
3115 ECP_VALIDATE_RET( d != NULL );
3116
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003117#if defined(ECP_MONTGOMERY)
3118 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003119 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003120 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003121 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
3122 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003123 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003124 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003125
3126 /* see [Curve25519] page 5 */
3127 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3128 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3129
3130 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003131 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003132#endif /* ECP_MONTGOMERY */
3133#if defined(ECP_SHORTWEIERSTRASS)
3134 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003135 {
3136 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003137 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3138 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3139 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003140 else
3141 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003142 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003143#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003144
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003145 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003146}
3147
3148/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003149 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003150 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003151int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3152 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003153 int (*f_rng)(void *, unsigned char *, size_t),
3154 void *p_rng )
3155{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003156 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003157 size_t n_size;
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003158#if defined(ECP_SHORTWEIERSTRASS)
3159 mbedtls_mpi one;
3160
3161 mbedtls_mpi_init( &one );
3162#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003163
3164 ECP_VALIDATE_RET( grp != NULL );
3165 ECP_VALIDATE_RET( d != NULL );
3166 ECP_VALIDATE_RET( f_rng != NULL );
3167
3168 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003169
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003170#if defined(ECP_MONTGOMERY)
3171 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003172 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003173 /* [M225] page 5 */
3174 size_t b;
3175
Janos Follath98e28a72016-05-31 14:03:54 +01003176 do {
3177 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3178 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003179
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003180 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003181 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003182 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003183 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003184 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003185 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003186
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003187 /* Make sure the last two bits are unset for Curve448, three bits for
3188 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003189 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3190 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003191 if( grp->nbits == 254 )
3192 {
3193 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3194 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003195 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003196#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003197
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003198#if defined(ECP_SHORTWEIERSTRASS)
3199 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003200 {
3201 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003202 int count = 0;
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003203 unsigned lt_lower = 1, lt_upper = 0;
3204
3205 MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &one, grp->N.n ) );
3206 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) );
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003207
3208 /*
3209 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3210 * - use the same byte ordering;
3211 * - keep the leftmost nbits bits of the generated octet string;
3212 * - try until result is in the desired range.
3213 * This also avoids any biais, which is especially important for ECDSA.
3214 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003215 do
3216 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003217 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003218 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003219
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003220 /*
3221 * Each try has at worst a probability 1/2 of failing (the msb has
3222 * a probability 1/2 of being 0, and then the result will be < N),
3223 * so after 30 tries failure probability is a most 2**(-30).
3224 *
3225 * For most curves, 1 try is enough with overwhelming probability,
3226 * since N starts with a lot of 1s in binary, but some curves
3227 * such as secp224k1 are actually very close to the worst case.
3228 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003229 if( ++count > 30 )
Janos Follath4c3408b2019-09-16 14:27:39 +01003230 {
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003231 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
Janos Follath4c3408b2019-09-16 14:27:39 +01003232 goto cleanup;
3233 }
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003234
3235 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &grp->N, &lt_upper ) );
3236 MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( d, &one, &lt_lower ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003237 }
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003238 while( lt_lower != 0 || lt_upper == 0 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003239 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003240#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003241
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003242cleanup:
Manuel Pégourié-Gonnardac127672021-06-01 12:06:57 +02003243#if defined(ECP_SHORTWEIERSTRASS)
3244 mbedtls_mpi_free( &one );
3245#endif
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003246 return( ret );
3247}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003248
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003249/*
3250 * Generate a keypair with configurable base point
3251 */
3252int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3253 const mbedtls_ecp_point *G,
3254 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3255 int (*f_rng)(void *, unsigned char *, size_t),
3256 void *p_rng )
3257{
3258 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003259 ECP_VALIDATE_RET( grp != NULL );
3260 ECP_VALIDATE_RET( d != NULL );
3261 ECP_VALIDATE_RET( G != NULL );
3262 ECP_VALIDATE_RET( Q != NULL );
3263 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003264
3265 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3266 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3267
3268cleanup:
3269 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003270}
3271
3272/*
3273 * Generate key pair, wrapper for conventional base point
3274 */
3275int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3276 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3277 int (*f_rng)(void *, unsigned char *, size_t),
3278 void *p_rng )
3279{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003280 ECP_VALIDATE_RET( grp != NULL );
3281 ECP_VALIDATE_RET( d != NULL );
3282 ECP_VALIDATE_RET( Q != NULL );
3283 ECP_VALIDATE_RET( f_rng != NULL );
3284
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003285 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003286}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003287
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003288/*
3289 * Generate a keypair, prettier wrapper
3290 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003291int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003292 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3293{
3294 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003295 ECP_VALIDATE_RET( key != NULL );
3296 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003297
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003298 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003299 return( ret );
3300
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003301 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003302}
3303
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003304/*
3305 * Check a public-private key pair
3306 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003307int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003308{
3309 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003310 mbedtls_ecp_point Q;
3311 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003312 ECP_VALIDATE_RET( pub != NULL );
3313 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003315 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003316 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003317 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3318 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3319 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003320 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003321 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003322 }
3323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003324 mbedtls_ecp_point_init( &Q );
3325 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003327 /* mbedtls_ecp_mul() needs a non-const group... */
3328 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003329
3330 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003331 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003333 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3334 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3335 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003336 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003337 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003338 goto cleanup;
3339 }
3340
3341cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003342 mbedtls_ecp_point_free( &Q );
3343 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003344
3345 return( ret );
3346}
3347
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003348#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003349
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003350#if defined(ECP_ONE_STEP_KDF)
3351/*
3352 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3353 * but unofficial ones can be found at:
3354 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3355 *
3356 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003357 * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +02003358 * less than one block).
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003359 */
3360#if defined(MBEDTLS_SHA512_C)
3361
3362static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003363 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
3364 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003365};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003366static const uint8_t test_kdf_out[40] = {
3367 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
3368 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
3369 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
3370 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
3371 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003372};
3373
3374#elif defined(MBEDTLS_SHA256_C)
3375
3376static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003377 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
3378 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003379};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003380static const uint8_t test_kdf_out[40] = {
3381 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
3382 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
3383 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
3384 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
3385 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003386};
3387
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003388#endif
3389
3390static int ecp_kdf_self_test( void )
3391{
3392 int ret;
3393 ecp_drbg_context kdf_ctx;
3394 mbedtls_mpi scalar;
3395 uint8_t out[sizeof( test_kdf_out )];
3396
3397 ecp_drbg_init( &kdf_ctx );
3398 mbedtls_mpi_init( &scalar );
3399 memset( out, 0, sizeof( out ) );
3400
3401 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3402 test_kdf_z, sizeof( test_kdf_z ) ) );
3403
3404 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3405 &scalar, sizeof( test_kdf_z ) ) );
3406
3407 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3408
3409 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3410 ret = -1;
3411
3412cleanup:
3413 ecp_drbg_free( &kdf_ctx );
3414 mbedtls_mpi_free( &scalar );
3415
3416 return( ret );
3417}
3418#endif /* ECP_ONE_STEP_KDF */
3419
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003420/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003421 * Checkup routine
3422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003423int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003424{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003425 int ret;
3426 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003427 mbedtls_ecp_group grp;
3428 mbedtls_ecp_point R, P;
3429 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003430 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003431 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003432 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003433 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003434 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003435 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003436 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003437 "400000000000000000000000000000000000000000000000", /* one and zeros */
3438 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3439 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003440 };
3441
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003442 mbedtls_ecp_group_init( &grp );
3443 mbedtls_ecp_point_init( &R );
3444 mbedtls_ecp_point_init( &P );
3445 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003446
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003447 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003448#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003449 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003450#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003451 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003452#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003453
3454 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003455 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003456
3457 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003458 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3459 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003460
3461 add_count = 0;
3462 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003463 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003464 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3465 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003466
3467 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3468 {
3469 add_c_prev = add_count;
3470 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003471 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003472 add_count = 0;
3473 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003474 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003476 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3477 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003478
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003479 if( add_count != add_c_prev ||
3480 dbl_count != dbl_c_prev ||
3481 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003482 {
3483 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003484 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003485
3486 ret = 1;
3487 goto cleanup;
3488 }
3489 }
3490
3491 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003492 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003493
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003494 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003495 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003496 /* We computed P = 2G last time, use it */
3497
3498 add_count = 0;
3499 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003500 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003501 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3502 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003503
3504 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3505 {
3506 add_c_prev = add_count;
3507 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003508 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003509 add_count = 0;
3510 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003511 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003513 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3514 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003515
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003516 if( add_count != add_c_prev ||
3517 dbl_count != dbl_c_prev ||
3518 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003519 {
3520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003521 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003522
3523 ret = 1;
3524 goto cleanup;
3525 }
3526 }
3527
3528 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003529 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003530
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003531#if defined(ECP_ONE_STEP_KDF)
3532 if( verbose != 0 )
3533 mbedtls_printf( " ECP test #3 (internal KDF): " );
3534
3535 ret = ecp_kdf_self_test();
3536 if( ret != 0 )
3537 {
3538 if( verbose != 0 )
3539 mbedtls_printf( "failed\n" );
3540
3541 ret = 1;
3542 goto cleanup;
3543 }
3544
3545 if( verbose != 0 )
3546 mbedtls_printf( "passed\n" );
3547#endif /* ECP_ONE_STEP_KDF */
3548
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003549cleanup:
3550
3551 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003552 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003554 mbedtls_ecp_group_free( &grp );
3555 mbedtls_ecp_point_free( &R );
3556 mbedtls_ecp_point_free( &P );
3557 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003558
3559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003560 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003561
3562 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003563}
3564
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003565#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003566
Janos Follathb0697532016-08-18 12:38:46 +01003567#endif /* !MBEDTLS_ECP_ALT */
3568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003569#endif /* MBEDTLS_ECP_C */