blob: 7ea8b1676a136ebad07e2bc8a01886f269f8c4eb [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010047 */
48
49/*
50 * References:
51 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010052 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010053 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010054 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010055 * RFC 4492 for the related TLS structures and constants
Nicholas Wilson08f3ef12015-11-10 13:10:01 +000056 * RFC 7748 for the Curve448 and Curve25519 curve definitions
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020057 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020058 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010059 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020060 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020061 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
62 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
63 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010064 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020065 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010066 * render ECC resistant against Side Channel Attacks. IACR Cryptology
67 * ePrint Archive, 2004, vol. 2004, p. 342.
68 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010069 */
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000072#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020073#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020075#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010076
Janos Follath683c5822018-12-07 12:09:25 +000077/**
78 * \brief Function level alternative implementation.
79 *
80 * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to
81 * replace certain functions in this module. The alternative implementations are
82 * typically hardware accelerators and need to activate the hardware before the
83 * computation starts and deactivate it after it finishes. The
84 * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve
85 * this purpose.
86 *
87 * To preserve the correct functionality the following conditions must hold:
88 *
89 * - The alternative implementation must be activated by
90 * mbedtls_internal_ecp_init() before any of the replaceable functions is
91 * called.
92 * - mbedtls_internal_ecp_free() must \b only be called when the alternative
93 * implementation is activated.
94 * - mbedtls_internal_ecp_init() must \b not be called when the alternative
95 * implementation is activated.
96 * - Public functions must not return while the alternative implementation is
97 * activated.
98 * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and
99 * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) )
100 * \endcode ensures that the alternative implementation supports the current
101 * group.
102 */
103#if defined(MBEDTLS_ECP_INTERNAL_ALT)
104#endif
105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100107
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000108#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +0000109#include "mbedtls/threading.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500110#include "mbedtls/platform_util.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200111
Rich Evans00ab4702015-02-06 13:43:58 +0000112#include <string.h>
113
Janos Follathb0697532016-08-18 12:38:46 +0100114#if !defined(MBEDTLS_ECP_ALT)
115
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000116/* Parameter validation macros based on platform_util.h */
117#define ECP_VALIDATE_RET( cond ) \
118 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
119#define ECP_VALIDATE( cond ) \
120 MBEDTLS_INTERNAL_VALIDATE( cond )
121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +0000123#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +0200124#else
Rich Evans00ab4702015-02-06 13:43:58 +0000125#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +0000126#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200128#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +0200130#endif
131
Janos Follath47d28f02016-11-01 13:22:05 +0000132#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +0100133
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200134#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200135#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200136#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200137#elif defined(MBEDTLS_CTR_DRBG_C)
138#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200139#elif defined(MBEDTLS_SHA512_C)
140#include "mbedtls/sha512.h"
141#elif defined(MBEDTLS_SHA256_C)
142#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200143#else
144#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
145#endif
146#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
147
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100148#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
149 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100150#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200151#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100154/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100155 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200156 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100157 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100158static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100159#endif
160
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200161#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
162/*
163 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard0defc572020-06-10 09:18:25 +0200164 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200165 * that people will pass non-NULL RNG when they care about side-channels, but
166 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
167 * no opportunity for the user to do anything about it.
168 *
169 * The obvious strategies for addressing that include:
170 * - change those APIs so that they take RNG arguments;
171 * - require a global RNG to be available to all crypto modules.
172 *
173 * Unfortunately those would break compatibility. So what we do instead is
174 * have our own internal DRBG instance, seeded from the secret scalar.
175 *
176 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200177 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200178 */
179
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200180#if defined(MBEDTLS_HMAC_DRBG_C)
181
182/* DRBG context type */
183typedef mbedtls_hmac_drbg_context ecp_drbg_context;
184
185/* DRBG context init */
186static inline void ecp_drbg_init( ecp_drbg_context *ctx )
187{
188 mbedtls_hmac_drbg_init( ctx );
189}
190
191/* DRBG context free */
192static inline void ecp_drbg_free( ecp_drbg_context *ctx )
193{
194 mbedtls_hmac_drbg_free( ctx );
195}
196
197/* DRBG function */
198static inline int ecp_drbg_random( void *p_rng,
199 unsigned char *output, size_t output_len )
200{
201 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
202}
203
204/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200205static int ecp_drbg_seed( ecp_drbg_context *ctx,
206 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200207{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200208 int ret;
209 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200210 /* The list starts with strong hashes */
211 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
212 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
213
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200214 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
215 secret_bytes, secret_len ) );
216
217 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
218
219cleanup:
220 mbedtls_platform_zeroize( secret_bytes, secret_len );
221
222 return( ret );
Manuel Pégourié-Gonnardc7295f52020-06-04 12:32:14 +0200223}
224
225#elif defined(MBEDTLS_CTR_DRBG_C)
226
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200227/* DRBG context type */
228typedef mbedtls_ctr_drbg_context ecp_drbg_context;
229
230/* DRBG context init */
231static inline void ecp_drbg_init( ecp_drbg_context *ctx )
232{
233 mbedtls_ctr_drbg_init( ctx );
234}
235
236/* DRBG context free */
237static inline void ecp_drbg_free( ecp_drbg_context *ctx )
238{
239 mbedtls_ctr_drbg_free( ctx );
240}
241
242/* DRBG function */
243static inline int ecp_drbg_random( void *p_rng,
244 unsigned char *output, size_t output_len )
245{
246 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
247}
248
249/*
250 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
251 * we need to pass an entropy function when seeding. So we use a dummy
252 * function for that, and pass the actual entropy as customisation string.
253 * (During seeding of CTR_DRBG the entropy input and customisation string are
254 * concatenated before being used to update the secret state.)
255 */
256static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
257{
258 (void) ctx;
259 memset( out, 0, len );
260 return( 0 );
261}
262
263/* DRBG context seeding */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200264static int ecp_drbg_seed( ecp_drbg_context *ctx,
265 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200266{
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200267 int ret;
268 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200269
Manuel Pégourié-Gonnard301a9ee2020-06-17 10:12:43 +0200270 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
271 secret_bytes, secret_len ) );
272
273 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
274 secret_bytes, secret_len );
275
276cleanup:
277 mbedtls_platform_zeroize( secret_bytes, secret_len );
278
279 return( ret );
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200280}
281
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200282#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200283
284/* This will be used in the self-test function */
285#define ECP_ONE_STEP_KDF
286
287/*
288 * We need to expand secret data (the scalar) into a longer stream of bytes.
289 *
290 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
291 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
292 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
293 *
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200294 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200295 */
296#if defined(MBEDTLS_SHA512_C)
297
298#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
299#define HASH_BLOCK_BYTES ( 512 / 8 )
300
301#elif defined(MBEDTLS_SHA256_C)
302
303#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
304#define HASH_BLOCK_BYTES ( 256 / 8 )
305
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200306#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200307
308/*
309 * State consists of a 32-bit counter plus the secret value.
310 *
311 * We stored them concatenated in a single buffer as that's what will get
312 * passed to the hash function.
313 */
314typedef struct {
315 size_t total_len;
316 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
317} ecp_drbg_context;
318
319static void ecp_drbg_init( ecp_drbg_context *ctx )
320{
321 memset( ctx, 0, sizeof( ecp_drbg_context ) );
322}
323
324static void ecp_drbg_free( ecp_drbg_context *ctx )
325{
326 mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
327}
328
329static int ecp_drbg_seed( ecp_drbg_context *ctx,
330 const mbedtls_mpi *secret, size_t secret_len )
331{
332 ctx->total_len = 4 + secret_len;
333 memset( ctx->buf, 0, 4);
334 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
335}
336
337static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
338{
339 ecp_drbg_context *ctx = p_rng;
340 int ret;
341 size_t len_done = 0;
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200342 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200343
344 while( len_done < output_len )
345 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200346 uint8_t use_len;
347
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200348 /* This function is only called for coordinate randomisation, which
349 * happens only twice in a scalar multiplication. Each time needs a
350 * random value in the range [2, p-1], and gets it by drawing len(p)
351 * bytes from this function, and retrying up to 10 times if unlucky.
352 *
353 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard2df58572020-06-18 12:14:34 +0200354 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
355 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard7d7c0042020-06-17 12:57:33 +0200356 *
357 * Since we don't need to draw more that 255 blocks, don't bother
358 * with carry propagation and just return an error instead. We can
359 * change that it we even need to draw more blinding values.
360 */
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200361 ctx->buf[3] += 1;
362 if( ctx->buf[3] == 0 )
363 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
364
365 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
366 if( ret != 0 )
367 return( ret );
368
369 if( output_len - len_done > HASH_BLOCK_BYTES )
370 use_len = HASH_BLOCK_BYTES;
371 else
372 use_len = output_len - len_done;
373
374 memcpy( output + len_done, tmp, use_len );
375 len_done += use_len;
376 }
377
Manuel Pégourié-Gonnarda90a95b2020-06-17 12:40:57 +0200378 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
379
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200380 return( 0 );
381}
382
383#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200384#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +0200385#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnardfb11d252020-05-22 12:12:36 +0200386#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
387
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200388#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100389/*
390 * Maximum number of "basic operations" to be done in a row.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +0200391 *
392 * Default value 0 means that ECC operations will not yield.
393 * Note that regardless of the value of ecp_max_ops, always at
394 * least one step is performed before yielding.
395 *
396 * Setting ecp_max_ops=1 can be suitable for testing purposes
397 * as it will interrupt computation at all possible points.
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100398 */
399static unsigned ecp_max_ops = 0;
400
401/*
402 * Set ecp_max_ops
403 */
404void mbedtls_ecp_set_max_ops( unsigned max_ops )
405{
406 ecp_max_ops = max_ops;
407}
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100408
409/*
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200410 * Check if restart is enabled
411 */
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200412int mbedtls_ecp_restart_is_enabled( void )
Manuel Pégourié-Gonnarda0c5bcc2017-04-21 11:33:57 +0200413{
414 return( ecp_max_ops != 0 );
415}
416
417/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200418 * Restart sub-context for ecp_mul_comb()
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100419 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200420struct mbedtls_ecp_restart_mul
421{
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100422 mbedtls_ecp_point R; /* current intermediate result */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +0100423 size_t i; /* current index in various loops, 0 outside */
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100424 mbedtls_ecp_point *T; /* table for precomputed points */
425 unsigned char T_size; /* number of points in table T */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200426 enum { /* what were we doing last time we returned? */
427 ecp_rsm_init = 0, /* nothing so far, dummy initial state */
428 ecp_rsm_pre_dbl, /* precompute 2^n multiples */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100429 ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */
430 ecp_rsm_pre_add, /* precompute remaining points by adding */
431 ecp_rsm_pre_norm_add, /* normalize all precomputed points */
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +0200432 ecp_rsm_comb_core, /* ecp_mul_comb_core() */
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +0100433 ecp_rsm_final_norm, /* do the final normalization */
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100434 } state;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200435#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
436 ecp_drbg_context drbg_ctx;
437 unsigned char drbg_seeded;
438#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100439};
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100440
441/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200442 * Init restart_mul sub-context
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +0100443 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200444static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100445{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200446 mbedtls_ecp_point_init( &ctx->R );
447 ctx->i = 0;
448 ctx->T = NULL;
449 ctx->T_size = 0;
450 ctx->state = ecp_rsm_init;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200451#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
452 ecp_drbg_init( &ctx->drbg_ctx );
453 ctx->drbg_seeded = 0;
454#endif
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100455}
456
457/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200458 * Free the components of a restart_mul sub-context
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100459 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200460static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100461{
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100462 unsigned char i;
463
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100464 if( ctx == NULL )
465 return;
Manuel Pégourié-Gonnard78d564a2017-03-14 11:48:38 +0100466
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +0100467 mbedtls_ecp_point_free( &ctx->R );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100468
Manuel Pégourié-Gonnard31f0ef72017-05-17 10:05:58 +0200469 if( ctx->T != NULL )
470 {
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +0100471 for( i = 0; i < ctx->T_size; i++ )
472 mbedtls_ecp_point_free( ctx->T + i );
473 mbedtls_free( ctx->T );
474 }
475
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +0200476#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
477 ecp_drbg_free( &ctx->drbg_ctx );
478#endif
479
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200480 ecp_restart_rsm_init( ctx );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +0100481}
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100482
483/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200484 * Restart context for ecp_muladd()
485 */
486struct mbedtls_ecp_restart_muladd
487{
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200488 mbedtls_ecp_point mP; /* mP value */
489 mbedtls_ecp_point R; /* R intermediate result */
490 enum { /* what should we do next? */
491 ecp_rsma_mul1 = 0, /* first multiplication */
492 ecp_rsma_mul2, /* second multiplication */
493 ecp_rsma_add, /* addition */
494 ecp_rsma_norm, /* normalization */
495 } state;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200496};
497
498/*
499 * Init restart_muladd sub-context
500 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200501static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200502{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200503 mbedtls_ecp_point_init( &ctx->mP );
504 mbedtls_ecp_point_init( &ctx->R );
505 ctx->state = ecp_rsma_mul1;
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200506}
507
508/*
509 * Free the components of a restart_muladd sub-context
510 */
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200511static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx )
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200512{
513 if( ctx == NULL )
514 return;
515
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200516 mbedtls_ecp_point_free( &ctx->mP );
517 mbedtls_ecp_point_free( &ctx->R );
518
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200519 ecp_restart_ma_init( ctx );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +0200520}
521
522/*
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200523 * Initialize a restart context
524 */
525void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx )
526{
Hanno Becker80f71682018-12-18 23:44:43 +0000527 ECP_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200528 ctx->ops_done = 0;
529 ctx->depth = 0;
530 ctx->rsm = NULL;
531 ctx->ma = NULL;
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200532}
533
534/*
535 * Free the components of a restart context
536 */
537void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx )
538{
539 if( ctx == NULL )
540 return;
541
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200542 ecp_restart_rsm_free( ctx->rsm );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200543 mbedtls_free( ctx->rsm );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200544
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200545 ecp_restart_ma_free( ctx->ma );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +0200546 mbedtls_free( ctx->ma );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200547
548 mbedtls_ecp_restart_init( ctx );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +0200549}
550
551/*
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100552 * Check if we can do the next step
553 */
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +0200554int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp,
555 mbedtls_ecp_restart_ctx *rs_ctx,
556 unsigned ops )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100557{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000558 ECP_VALIDATE_RET( grp != NULL );
559
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200560 if( rs_ctx != NULL && ecp_max_ops != 0 )
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100561 {
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100562 /* scale depending on curve size: the chosen reference is 256-bit,
563 * and multiplication is quadratic. Round to the closest integer. */
564 if( grp->pbits >= 512 )
565 ops *= 4;
566 else if( grp->pbits >= 384 )
567 ops *= 2;
568
Hanno Beckerb10c6602018-10-26 13:50:13 +0100569 /* Avoid infinite loops: always allow first step.
570 * Because of that, however, it's not generally true
571 * that ops_done <= ecp_max_ops, so the check
572 * ops_done > ecp_max_ops below is mandatory. */
573 if( ( rs_ctx->ops_done != 0 ) &&
574 ( rs_ctx->ops_done > ecp_max_ops ||
575 ops > ecp_max_ops - rs_ctx->ops_done ) )
576 {
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100577 return( MBEDTLS_ERR_ECP_IN_PROGRESS );
Hanno Beckerb10c6602018-10-26 13:50:13 +0100578 }
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100579
Manuel Pégourié-Gonnarde6854492017-03-20 14:35:19 +0100580 /* update running count */
Manuel Pégourié-Gonnard646393b2017-04-20 10:03:45 +0200581 rs_ctx->ops_done += ops;
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +0100582 }
583
584 return( 0 );
585}
586
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200587/* Call this when entering a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200588#define ECP_RS_ENTER( SUB ) do { \
589 /* reset ops count for this call if top-level */ \
590 if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \
591 rs_ctx->ops_done = 0; \
592 \
593 /* set up our own sub-context if needed */ \
594 if( mbedtls_ecp_restart_is_enabled() && \
595 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
596 { \
597 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
598 if( rs_ctx->SUB == NULL ) \
599 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
600 \
601 ecp_restart_## SUB ##_init( rs_ctx->SUB ); \
602 } \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200603} while( 0 )
604
605/* Call this when leaving a function that needs its own sub-context */
Manuel Pégourié-Gonnarda58e0112018-10-16 10:42:47 +0200606#define ECP_RS_LEAVE( SUB ) do { \
607 /* clear our sub-context when not in progress (done or error) */ \
608 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
609 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
610 { \
611 ecp_restart_## SUB ##_free( rs_ctx->SUB ); \
612 mbedtls_free( rs_ctx->SUB ); \
613 rs_ctx->SUB = NULL; \
614 } \
615 \
616 if( rs_ctx != NULL ) \
617 rs_ctx->depth--; \
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +0200618} while( 0 )
619
620#else /* MBEDTLS_ECP_RESTARTABLE */
621
622#define ECP_RS_ENTER( sub ) (void) rs_ctx;
623#define ECP_RS_LEAVE( sub ) (void) rs_ctx;
624
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +0200625#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard054433c2017-03-22 11:18:33 +0100626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
628 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
629 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
630 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
631 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
632 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
633 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
634 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
635 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
636 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
637 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200638#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100639#endif
640
Nicholas Wilson08f3ef12015-11-10 13:10:01 +0000641#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
642 defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200643#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100644#endif
645
646/*
647 * Curve types: internal for now, might be exposed later
648 */
649typedef enum
650{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200651 ECP_TYPE_NONE = 0,
652 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
653 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100654} ecp_curve_type;
655
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100656/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200657 * List of supported curves:
658 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200659 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200660 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200661 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100662 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100663 * Curves are listed in order: largest curves first, and for a given size,
664 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200665 *
666 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200669{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
671 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200672#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
674 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100675#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
677 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200678#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
680 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100681#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
683 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200684#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
686 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100687#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
689 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100690#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
692 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200693#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
695 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100696#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
698 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100699#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
701 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100702#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200704};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100705
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200706#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
707 sizeof( ecp_supported_curves[0] )
708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200710
711/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200712 * List of supported curves and associated info
713 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200715{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200716 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200717}
718
719/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100720 * List of supported curves, group ID only
721 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100723{
724 static int init_done = 0;
725
726 if( ! init_done )
727 {
728 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 for( curve_info = mbedtls_ecp_curve_list();
732 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100733 curve_info++ )
734 {
735 ecp_supported_grp_id[i++] = curve_info->grp_id;
736 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100738
739 init_done = 1;
740 }
741
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200742 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100743}
744
745/*
746 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200747 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748const 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 +0200749{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 for( curve_info = mbedtls_ecp_curve_list();
753 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200754 curve_info++ )
755 {
756 if( curve_info->grp_id == grp_id )
757 return( curve_info );
758 }
759
760 return( NULL );
761}
762
763/*
764 * Get the curve info from the TLS identifier
765 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200767{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200769
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 for( curve_info = mbedtls_ecp_curve_list();
771 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200772 curve_info++ )
773 {
774 if( curve_info->tls_id == tls_id )
775 return( curve_info );
776 }
777
778 return( NULL );
779}
780
781/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100782 * Get the curve info from the name
783 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100785{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200786 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100787
Hanno Beckerb7a04a72018-12-18 23:50:21 +0000788 if( name == NULL )
789 return( NULL );
790
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791 for( curve_info = mbedtls_ecp_curve_list();
792 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100793 curve_info++ )
794 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200795 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100796 return( curve_info );
797 }
798
799 return( NULL );
800}
801
802/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100803 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100804 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100806{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100807 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200808 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100809
810 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200811 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100812 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200813 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100814}
815
816/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100817 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100818 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100820{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000821 ECP_VALIDATE( pt != NULL );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 mbedtls_mpi_init( &pt->X );
824 mbedtls_mpi_init( &pt->Y );
825 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100826}
827
828/*
829 * Initialize (the components of) a group
830 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100832{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000833 ECP_VALIDATE( grp != NULL );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100834
Manuel Pégourié-Gonnard95e2eca2018-06-20 10:29:47 +0200835 grp->id = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200836 mbedtls_mpi_init( &grp->P );
837 mbedtls_mpi_init( &grp->A );
838 mbedtls_mpi_init( &grp->B );
839 mbedtls_ecp_point_init( &grp->G );
840 mbedtls_mpi_init( &grp->N );
841 grp->pbits = 0;
842 grp->nbits = 0;
843 grp->h = 0;
844 grp->modp = NULL;
845 grp->t_pre = NULL;
846 grp->t_post = NULL;
847 grp->t_data = NULL;
848 grp->T = NULL;
849 grp->T_size = 0;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100850}
851
852/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200853 * Initialize (the components of) a key pair
854 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200856{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000857 ECP_VALIDATE( key != NULL );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 mbedtls_ecp_group_init( &key->grp );
860 mbedtls_mpi_init( &key->d );
861 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200862}
863
864/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100865 * Unallocate (the components of) a point
866 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100868{
869 if( pt == NULL )
870 return;
871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 mbedtls_mpi_free( &( pt->X ) );
873 mbedtls_mpi_free( &( pt->Y ) );
874 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100875}
876
877/*
878 * Unallocate (the components of) a group
879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100881{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200882 size_t i;
883
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100884 if( grp == NULL )
885 return;
886
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100887 if( grp->h != 1 )
888 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200889 mbedtls_mpi_free( &grp->P );
890 mbedtls_mpi_free( &grp->A );
891 mbedtls_mpi_free( &grp->B );
892 mbedtls_ecp_point_free( &grp->G );
893 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100894 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200895
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200896 if( grp->T != NULL )
897 {
898 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 mbedtls_ecp_point_free( &grp->T[i] );
900 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200901 }
902
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500903 mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100904}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100905
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100906/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200907 * Unallocate (the components of) a key pair
908 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200910{
Paul Bakker66d5d072014-06-17 16:39:18 +0200911 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200912 return;
913
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 mbedtls_ecp_group_free( &key->grp );
915 mbedtls_mpi_free( &key->d );
916 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200917}
918
919/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200920 * Copy the contents of a point
921 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200923{
924 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000925 ECP_VALIDATE_RET( P != NULL );
926 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200927
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200928 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
929 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
930 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200931
932cleanup:
933 return( ret );
934}
935
936/*
937 * Copy the contents of a group object
938 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200940{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000941 ECP_VALIDATE_RET( dst != NULL );
942 ECP_VALIDATE_RET( src != NULL );
943
944 return( mbedtls_ecp_group_load( dst, src->id ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200945}
946
947/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100948 * Set point to zero
949 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100951{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100952 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000953 ECP_VALIDATE_RET( pt != NULL );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100954
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200955 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
956 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
957 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100958
959cleanup:
960 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100961}
962
963/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100964 * Tell if a point is zero
965 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100967{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000968 ECP_VALIDATE_RET( pt != NULL );
969
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200970 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100971}
972
973/*
Brian J Murrayf343de12018-10-22 16:40:49 -0700974 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200975 */
976int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
977 const mbedtls_ecp_point *Q )
978{
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000979 ECP_VALIDATE_RET( P != NULL );
980 ECP_VALIDATE_RET( Q != NULL );
981
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200982 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
983 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
984 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
985 {
986 return( 0 );
987 }
988
989 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
990}
991
992/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100993 * Import a non-zero point from ASCII strings
994 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100996 const char *x, const char *y )
997{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100998 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +0000999 ECP_VALIDATE_RET( P != NULL );
1000 ECP_VALIDATE_RET( x != NULL );
1001 ECP_VALIDATE_RET( y != NULL );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
1004 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
1005 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001006
1007cleanup:
1008 return( ret );
1009}
1010
1011/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001012 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001013 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001014int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp,
1015 const mbedtls_ecp_point *P,
1016 int format, size_t *olen,
1017 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001018{
Paul Bakkera280d0f2013-04-08 13:40:17 +02001019 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001020 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001021 ECP_VALIDATE_RET( grp != NULL );
1022 ECP_VALIDATE_RET( P != NULL );
1023 ECP_VALIDATE_RET( olen != NULL );
1024 ECP_VALIDATE_RET( buf != NULL );
1025 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1026 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001027
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001028 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001029 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001032 {
1033 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001035
1036 buf[0] = 0x00;
1037 *olen = 1;
1038
1039 return( 0 );
1040 }
1041
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001043
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001045 {
1046 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001047
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001048 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001049 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001050
1051 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
1053 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001054 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001056 {
1057 *olen = plen + 1;
1058
1059 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001060 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
1063 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +01001064 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +01001065
1066cleanup:
1067 return( ret );
1068}
1069
1070/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001071 * Import a point from unsigned binary data (SEC1 2.3.4)
1072 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001073int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp,
1074 mbedtls_ecp_point *pt,
1075 const unsigned char *buf, size_t ilen )
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001076{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001077 int ret;
1078 size_t plen;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001079 ECP_VALIDATE_RET( grp != NULL );
1080 ECP_VALIDATE_RET( pt != NULL );
1081 ECP_VALIDATE_RET( buf != NULL );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001082
Paul Bakker82788fb2014-10-20 13:59:19 +02001083 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001084 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001085
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001086 if( buf[0] == 0x00 )
1087 {
1088 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001090 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +01001092 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001095
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001096 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001097 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +01001098
1099 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001100 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001101
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001102 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
1103 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
1104 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +01001105
1106cleanup:
1107 return( ret );
1108}
1109
1110/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001111 * Import a point from a TLS ECPoint record (RFC 4492)
1112 * struct {
1113 * opaque point <1..2^8-1>;
1114 * } ECPoint;
1115 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001116int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp,
1117 mbedtls_ecp_point *pt,
1118 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001119{
1120 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001121 const unsigned char *buf_start;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001122 ECP_VALIDATE_RET( grp != NULL );
1123 ECP_VALIDATE_RET( pt != NULL );
1124 ECP_VALIDATE_RET( buf != NULL );
1125 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001126
1127 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +02001128 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001129 */
1130 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001132
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001133 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001134 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001136
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +01001137 /*
1138 * Save buffer start for read_binary and update buf
1139 */
1140 buf_start = *buf;
1141 *buf += data_len;
1142
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001143 return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001144}
1145
1146/*
1147 * Export a point as a TLS ECPoint record (RFC 4492)
1148 * struct {
1149 * opaque point <1..2^8-1>;
1150 * } ECPoint;
1151 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001152int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001153 int format, size_t *olen,
1154 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001155{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001156 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001157 ECP_VALIDATE_RET( grp != NULL );
1158 ECP_VALIDATE_RET( pt != NULL );
1159 ECP_VALIDATE_RET( olen != NULL );
1160 ECP_VALIDATE_RET( buf != NULL );
1161 ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED ||
1162 format == MBEDTLS_ECP_PF_COMPRESSED );
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001163
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001164 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001165 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001166 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001167 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001171 olen, buf + 1, blen - 1) ) != 0 )
1172 return( ret );
1173
1174 /*
1175 * write length to the first byte and update total length
1176 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001177 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +01001178 ++*olen;
1179
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001180 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +01001181}
1182
1183/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001184 * Set a group from an ECParameters record (RFC 4492)
1185 */
Janos Follath89ac8c92018-10-30 11:24:05 +00001186int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
1187 const unsigned char **buf, size_t len )
1188{
1189 int ret;
1190 mbedtls_ecp_group_id grp_id;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001191 ECP_VALIDATE_RET( grp != NULL );
1192 ECP_VALIDATE_RET( buf != NULL );
1193 ECP_VALIDATE_RET( *buf != NULL );
Janos Follath89ac8c92018-10-30 11:24:05 +00001194
1195 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 )
1196 return( ret );
1197
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001198 return( mbedtls_ecp_group_load( grp, grp_id ) );
Janos Follath89ac8c92018-10-30 11:24:05 +00001199}
1200
1201/*
1202 * Read a group id from an ECParameters record (RFC 4492) and convert it to
1203 * mbedtls_ecp_group_id.
1204 */
1205int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp,
1206 const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001207{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001208 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001209 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001210 ECP_VALIDATE_RET( grp != NULL );
1211 ECP_VALIDATE_RET( buf != NULL );
1212 ECP_VALIDATE_RET( *buf != NULL );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001213
1214 /*
1215 * We expect at least three bytes (see below)
1216 */
1217 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001218 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001219
1220 /*
1221 * First byte is curve_type; only named_curve is handled
1222 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001223 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
1224 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001225
1226 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001227 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +01001228 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001229 tls_id = *(*buf)++;
1230 tls_id <<= 8;
1231 tls_id |= *(*buf)++;
1232
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
1234 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001235
Janos Follath89ac8c92018-10-30 11:24:05 +00001236 *grp = curve_info->grp_id;
1237
1238 return( 0 );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001239}
1240
1241/*
1242 * Write the ECParameters record corresponding to a group (RFC 4492)
1243 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001244int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001245 unsigned char *buf, size_t blen )
1246{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247 const mbedtls_ecp_curve_info *curve_info;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00001248 ECP_VALIDATE_RET( grp != NULL );
1249 ECP_VALIDATE_RET( buf != NULL );
1250 ECP_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
1253 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001254
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001255 /*
1256 * We are going to write 3 bytes (see below)
1257 */
1258 *olen = 3;
1259 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001261
1262 /*
1263 * First byte is curve_type, always named_curve
1264 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001265 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001266
1267 /*
1268 * Next two bytes are the namedcurve value
1269 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +02001270 buf[0] = curve_info->tls_id >> 8;
1271 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +01001272
Paul Bakkerd8bb8262014-06-17 14:06:49 +02001273 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +01001274}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001275
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001276/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
1278 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001279 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 * 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 +02001281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001283{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001284 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001285
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001286 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001288
1289 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001291 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001292 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001294 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001295
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001296 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001297
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001298 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001299 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
1300 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001302 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001303 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001305
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +02001306cleanup:
1307 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +02001308}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +02001309
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +01001310/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001311 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001312 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001313 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 * 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 +01001315 * bring the result back to this range.
1316 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001317 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +01001318 */
1319
1320/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 * 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 +01001322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01001324#define INC_MUL_COUNT mul_count++;
1325#else
1326#define INC_MUL_COUNT
1327#endif
1328
Hanno Beckerd6028a12018-10-15 12:01:35 +01001329#define MOD_MUL( N ) \
1330 do \
1331 { \
1332 MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \
1333 INC_MUL_COUNT \
1334 } while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001335
1336/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001337 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +02001338 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001339 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001340#define MOD_SUB( N ) \
1341 while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001343
1344/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001345 * 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 +02001346 * We known P, N and the result are positive, so sub_abs is correct, and
1347 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001348 */
Hanno Beckerd6028a12018-10-15 12:01:35 +01001349#define MOD_ADD( N ) \
1350 while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001352
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001353#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001354/*
1355 * For curves in short Weierstrass form, we do all the internal operations in
1356 * Jacobian coordinates.
1357 *
1358 * For multiplication, we'll use a comb method with coutermeasueres against
1359 * SPA, hence timing attacks.
1360 */
1361
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001362/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001363 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001364 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001367{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001368 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001369 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001371 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001372 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001373
Janos Follathb0697532016-08-18 12:38:46 +01001374#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001375 if( mbedtls_internal_ecp_grp_capable( grp ) )
1376 return( mbedtls_internal_ecp_normalize_jac( grp, pt ) );
Janos Follath372697b2016-10-28 16:53:11 +01001377#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001380
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001381 /*
1382 * X = X / Z^2 mod p
1383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1385 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1386 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 +01001387
1388 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001389 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001390 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1392 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 +01001393
1394 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001395 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001398
1399cleanup:
1400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001402
1403 return( ret );
1404}
1405
1406/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001407 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001408 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001409 * (See for example Cohen's "A Course in Computational Algebraic Number
1410 * Theory", Algorithm 10.3.4.)
1411 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001412 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001413 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001414 *
1415 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001416 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001417static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001418 mbedtls_ecp_point *T[], size_t T_size )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001419{
1420 int ret;
1421 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001423
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001424 if( T_size < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001425 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001426
Janos Follathb0697532016-08-18 12:38:46 +01001427#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001428 if( mbedtls_internal_ecp_grp_capable( grp ) )
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001429 return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) );
Janos Follathb0697532016-08-18 12:38:46 +01001430#endif
1431
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001432 if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001433 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001434
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02001435 for( i = 0; i < T_size; i++ )
1436 mbedtls_mpi_init( &c[i] );
1437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001439
1440 /*
1441 * c[i] = Z_0 * ... * Z_i
1442 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001444 for( i = 1; i < T_size; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001447 MOD_MUL( c[i] );
1448 }
1449
1450 /*
1451 * u = 1 / (Z_0 * ... * Z_n) mod P
1452 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001453 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001454
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001455 for( i = T_size - 1; ; i-- )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001456 {
1457 /*
1458 * Zi = 1 / Z_i mod p
1459 * u = 1 / (Z_0 * ... * Z_i) mod P
1460 */
1461 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001462 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001463 }
1464 else
1465 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1467 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001468 }
1469
1470 /*
1471 * proceed as in normalize()
1472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1474 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1475 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1476 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 +01001477
1478 /*
1479 * Post-precessing: reclaim some memory by shrinking coordinates
1480 * - not storing Z (always 1)
1481 * - shrinking other coordinates, but still keeping the same number of
1482 * limbs as P, as otherwise it will too likely be regrown too fast.
1483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1485 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1486 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001487
1488 if( i == 0 )
1489 break;
1490 }
1491
1492cleanup:
1493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001495 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 mbedtls_mpi_free( &c[i] );
1497 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001498
1499 return( ret );
1500}
1501
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001502/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001503 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1504 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1505 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1507 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001508 unsigned char inv )
1509{
1510 int ret;
1511 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001512 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001515
1516 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001517 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1518 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1519 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001520
1521cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001523
1524 return( ret );
1525}
1526
1527/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001528 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001529 *
Peter Dettmance661b22015-02-07 14:43:51 +07001530 * 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 +01001531 *
Peter Dettmance661b22015-02-07 14:43:51 +07001532 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1533 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1534 *
1535 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1536 *
1537 * Cost: 1D := 3M + 4S (A == 0)
1538 * 4M + 4S (A == -3)
1539 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001540 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1542 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001543{
1544 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001545 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001548 dbl_count++;
1549#endif
1550
Janos Follathb0697532016-08-18 12:38:46 +01001551#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001552 if( mbedtls_internal_ecp_grp_capable( grp ) )
1553 return( mbedtls_internal_ecp_double_jac( grp, R, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01001554#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001555
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001556 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 +01001557
1558 /* Special case for A = -3 */
1559 if( grp->A.p == NULL )
1560 {
Peter Dettmance661b22015-02-07 14:43:51 +07001561 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001562 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1563 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1564 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1565 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1566 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001567 }
1568 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001569 {
Peter Dettmance661b22015-02-07 14:43:51 +07001570 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001571 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1572 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001573
1574 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001575 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001576 {
1577 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001578 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1579 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1580 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1581 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001582 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001583 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001584
Peter Dettmance661b22015-02-07 14:43:51 +07001585 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1587 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1588 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1589 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001590
Peter Dettmance661b22015-02-07 14:43:51 +07001591 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001592 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1593 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001594
1595 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001596 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1597 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1598 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001599
1600 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001601 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1602 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1603 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001604
1605 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001606 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1607 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001608
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1610 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1611 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001612
1613cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001614 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 +02001615
1616 return( ret );
1617}
1618
1619/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001620 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001621 *
1622 * The coordinates of Q must be normalized (= affine),
1623 * but those of P don't need to. R is not normalized.
1624 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001625 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001626 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001627 * - at each step, P, Q and R are multiples of the base point, the factor
1628 * being less than its order, so none of them is zero;
1629 * - Q is an odd multiple of the base point, P an even multiple,
1630 * due to the choice of precomputed points in the modified comb method.
1631 * So branches for these cases do not leak secret information.
1632 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001633 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1634 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001635 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1638 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001639{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001640 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001642
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001643#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001644 add_count++;
1645#endif
1646
Janos Follathb0697532016-08-18 12:38:46 +01001647#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001648 if( mbedtls_internal_ecp_grp_capable( grp ) )
1649 return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) );
Janos Follath372697b2016-10-28 16:53:11 +01001650#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001651
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001652 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001653 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001654 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1656 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1659 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001660
1661 /*
1662 * Make sure Q coordinates are normalized
1663 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001664 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1665 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001667 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1668 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1671 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1672 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1673 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1674 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001676
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001677 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001679 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001680 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001681 {
1682 ret = ecp_double_jac( grp, R, P );
1683 goto cleanup;
1684 }
1685 else
1686 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001688 goto cleanup;
1689 }
1690 }
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1693 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1694 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1695 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1696 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1697 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1698 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1699 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1700 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1701 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1702 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1703 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1707 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001708
1709cleanup:
1710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001711 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1712 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001713
1714 return( ret );
1715}
1716
1717/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001718 * Randomize jacobian coordinates:
1719 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001720 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001721 *
1722 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001723 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001724static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001725 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1726{
1727 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001729 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001730 int count = 0;
1731
Janos Follathb0697532016-08-18 12:38:46 +01001732#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02001733 if( mbedtls_internal_ecp_grp_capable( grp ) )
1734 return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) );
Janos Follath372697b2016-10-28 16:53:11 +01001735#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001736
1737 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001739
1740 /* Generate l such that 1 < l < p */
1741 do
1742 {
Ron Eldorca6ff582017-01-12 14:50:50 +02001743 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001744
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1746 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001747
1748 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09001749 {
1750 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1751 goto cleanup;
1752 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001753 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001755
1756 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001757 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 +02001758
1759 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1761 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 +02001762
1763 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001764 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1765 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 +02001766
1767cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001768 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001769
1770 return( ret );
1771}
1772
1773/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001774 * Check and define parameters used by the comb method (see below for details)
1775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1777#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001778#endif
1779
1780/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001781#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001782
1783/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001784#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001785
1786/*
1787 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001788 *
1789 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001790 * modified version that provides resistance to SPA by avoiding zero
1791 * digits in the representation as in [3]. We modify the method further by
1792 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001793 * representation uses one more K_i, due to carries, but saves on the size of
1794 * the precomputed table.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001795 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001796 * Summary of the comb method and its modifications:
1797 *
1798 * - The goal is to compute m*P for some w*d-bit integer m.
1799 *
1800 * - The basic comb method splits m into the w-bit integers
1801 * x[0] .. x[d-1] where x[i] consists of the bits in m whose
1802 * index has residue i modulo d, and computes m * P as
1803 * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where
1804 * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P.
1805 *
1806 * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by
1807 * .. + 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]] ..,
1808 * thereby successively converting it into a form where all summands
1809 * are nonzero, at the cost of negative summands. This is the basic idea of [3].
1810 *
1811 * - More generally, even if x[i+1] != 0, we can first transform the sum as
1812 * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] ..,
1813 * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]].
1814 * Performing and iterating this procedure for those x[i] that are even
1815 * (keeping track of carry), we can transform the original sum into one of the form
1816 * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]]
1817 * with all x'[i] odd. It is therefore only necessary to know S at odd indices,
1818 * which is why we are only computing half of it in the first place in
1819 * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb.
1820 *
1821 * - For the sake of compactness, only the seven low-order bits of x[i]
1822 * are used to represent its absolute value (K_i in the paper), and the msb
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001823 * 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 +02001824 * if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001825 *
1826 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001827 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001828 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001829 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001830 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1831 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001832 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01001833static void ecp_comb_recode_core( unsigned char x[], size_t d,
1834 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001835{
1836 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001837 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001838
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001839 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001840
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001841 /* First get the classical comb values (except for x_d = 0) */
1842 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001843 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001844 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001845
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001846 /* Now make sure x_1 .. x_d are odd */
1847 c = 0;
1848 for( i = 1; i <= d; i++ )
1849 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001850 /* Add carry and update it */
1851 cc = x[i] & c;
1852 x[i] = x[i] ^ c;
1853 c = cc;
1854
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001855 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001856 adjust = 1 - ( x[i] & 0x01 );
1857 c |= x[i] & ( x[i-1] * adjust );
1858 x[i] = x[i] ^ ( x[i-1] * adjust );
1859 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001860 }
1861}
1862
1863/*
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001864 * Precompute points for the adapted comb method
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001865 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001866 * Assumption: T must be able to hold 2^{w - 1} elements.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001867 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001868 * Operation: If i = i_{w-1} ... i_1 is the binary representation of i,
1869 * 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 +01001870 *
1871 * 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 +02001872 *
1873 * Note: Even comb values (those where P would be omitted from the
1874 * sum defining T[i] above) are not needed in our adaption
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001875 * the comb method. See ecp_comb_recode_core().
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001876 *
1877 * This function currently works in four steps:
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001878 * (1) [dbl] Computation of intermediate T[i] for 2-power values of i
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001879 * (2) [norm_dbl] Normalization of coordinates of these T[i]
1880 * (3) [add] Computation of all T[i]
1881 * (4) [norm_add] Normalization of all T[i]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02001882 *
1883 * Step 1 can be interrupted but not the others; together with the final
1884 * coordinate normalization they are the largest steps done at once, depending
1885 * on the window size. Here are operation counts for P-256:
1886 *
1887 * step (2) (3) (4)
1888 * w = 5 142 165 208
1889 * w = 4 136 77 160
1890 * w = 3 130 33 136
1891 * w = 2 124 11 124
1892 *
1893 * So if ECC operations are blocking for too long even with a low max_ops
1894 * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order
1895 * to minimize maximum blocking time.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001896 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001897static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1898 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001899 unsigned char w, size_t d,
1900 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001901{
1902 int ret;
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001903 unsigned char i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001904 size_t j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001905 const unsigned char T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001907
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001908#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001909 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001910 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001911 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
1912 goto dbl;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001913 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl )
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001914 goto norm_dbl;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001915 if( rs_ctx->rsm->state == ecp_rsm_pre_add )
1916 goto add;
1917 if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add )
1918 goto norm_add;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001919 }
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001920#else
1921 (void) rs_ctx;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01001922#endif
1923
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001924#if defined(MBEDTLS_ECP_RESTARTABLE)
1925 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1926 {
1927 rs_ctx->rsm->state = ecp_rsm_pre_dbl;
1928
1929 /* initial state for the loop */
1930 rs_ctx->rsm->i = 0;
1931 }
1932
1933dbl:
1934#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001935 /*
1936 * Set T[0] = P and
1937 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
1938 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001939 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001940
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001941#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02001942 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
1943 j = rs_ctx->rsm->i;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001944 else
1945#endif
1946 j = 0;
1947
1948 for( ; j < d * ( w - 1 ); j++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001949 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001950 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL );
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01001951
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001952 i = 1U << ( j / d );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001953 cur = T + i;
Manuel Pégourié-Gonnardae557072017-03-20 12:21:24 +01001954
1955 if( j % d == 0 )
1956 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
1957
1958 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001959 }
1960
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001961#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001962 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1963 rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl;
1964
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001965norm_dbl:
1966#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001967 /*
1968 * Normalize current elements in T. As T has holes,
1969 * use an auxiliary array of pointers to elements in T.
1970 */
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001971 j = 0;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001972 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001973 TT[j++] = T + i;
1974
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02001975 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001976
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01001977 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001978
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001979#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001980 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
1981 rs_ctx->rsm->state = ecp_rsm_pre_add;
1982
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001983add:
1984#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02001985 /*
1986 * Compute the remaining ones using the minimal number of additions
1987 * Be careful to update T[2^l] only after using it!
1988 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001989 MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01001990
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02001991 for( i = 1; i < T_size; i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001992 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001993 j = i;
1994 while( j-- )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001995 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001996 }
1997
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02001998#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02001999 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2000 rs_ctx->rsm->state = ecp_rsm_pre_norm_add;
2001
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01002002norm_add:
2003#endif
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002004 /*
Manuel Pégourié-Gonnarda966fde2018-10-23 10:41:11 +02002005 * Normalize final elements in T. Even though there are no holes now, we
2006 * still need the auxiliary array for homogeneity with the previous
2007 * call. Also, skip T[0] which is already normalised, being a copy of P.
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002008 */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002009 for( j = 0; j + 1 < T_size; j++ )
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002010 TT[j] = T + j + 1;
2011
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002012 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 );
Manuel Pégourié-Gonnarde2d7cb32017-03-20 10:24:17 +01002013
Manuel Pégourié-Gonnardfc3e0be2017-03-20 09:29:31 +01002014 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01002015
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002016cleanup:
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002017#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002018 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2019 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002020 {
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002021 if( rs_ctx->rsm->state == ecp_rsm_pre_dbl )
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002022 rs_ctx->rsm->i = j;
Manuel Pégourié-Gonnard213541a2017-03-20 12:50:41 +01002023 }
2024#endif
Janos Follathb0697532016-08-18 12:38:46 +01002025
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002026 return( ret );
2027}
2028
2029/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01002030 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002031 *
2032 * See ecp_comb_recode_core() for background
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002033 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002035 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002036 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002037{
2038 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002039 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002040
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002041 /* Ignore the "sign" bit and scale down */
2042 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002043
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002044 /* Read the whole table to thwart cache-based timing attacks */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002045 for( j = 0; j < T_size; j++ )
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002046 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
2048 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002049 }
2050
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01002051 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002053
2054cleanup:
2055 return( ret );
2056}
2057
2058/*
2059 * Core multiplication algorithm for the (modified) comb method.
2060 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01002061 *
2062 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002065 const mbedtls_ecp_point T[], unsigned char T_size,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01002066 const unsigned char x[], size_t d,
2067 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002068 void *p_rng,
2069 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002070{
2071 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002073 size_t i;
2074
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002076
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002077#if !defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002078 (void) rs_ctx;
2079#endif
2080
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002081#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002082 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2083 rs_ctx->rsm->state != ecp_rsm_comb_core )
2084 {
2085 rs_ctx->rsm->i = 0;
2086 rs_ctx->rsm->state = ecp_rsm_comb_core;
2087 }
2088
2089 /* new 'if' instead of nested for the sake of the 'else' branch */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002090 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002091 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002092 /* restore current index (R already pointing to rs_ctx->rsm->R) */
2093 i = rs_ctx->rsm->i;
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002094 }
2095 else
2096#endif
2097 {
2098 /* Start with a non-zero point and randomize its coordinates */
2099 i = d;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002100 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002101 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002102#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002103 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002104#endif
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002105 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
2106 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002107
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002108 while( i != 0 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002109 {
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002110 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002111 --i;
2112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002113 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002114 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002115 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002116 }
2117
2118cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002119
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002120 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002121
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002122#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002123 if( rs_ctx != NULL && rs_ctx->rsm != NULL &&
2124 ret == MBEDTLS_ERR_ECP_IN_PROGRESS )
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002125 {
Manuel Pégourié-Gonnard90f31b72018-10-16 10:45:24 +02002126 rs_ctx->rsm->i = i;
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002127 /* no need to save R, already pointing to rs_ctx->rsm->R */
Manuel Pégourié-Gonnardc5d844b2017-03-15 13:06:28 +01002128 }
2129#endif
2130
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002131 return( ret );
2132}
2133
2134/*
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002135 * Recode the scalar to get constant-time comb multiplication
2136 *
2137 * As the actual scalar recoding needs an odd scalar as a starting point,
2138 * this wrapper ensures that by replacing m by N - m if necessary, and
2139 * informs the caller that the result of multiplication will be negated.
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002140 *
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002141 * This works because we only support large prime order for Short Weierstrass
2142 * curves, so N is always odd hence either m or N - m is.
2143 *
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002144 * See ecp_comb_recode_core() for background.
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002145 */
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002146static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
2147 const mbedtls_mpi *m,
2148 unsigned char k[COMB_MAX_D + 1],
2149 size_t d,
2150 unsigned char w,
2151 unsigned char *parity_trick )
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002152{
2153 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002154 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002155
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002156 mbedtls_mpi_init( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002157 mbedtls_mpi_init( &mm );
2158
Manuel Pégourié-Gonnardfd87e352017-08-24 14:21:05 +02002159 /* N is always odd (see above), just make extra sure */
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002160 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
2161 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
2162
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002163 /* do we need the parity trick? */
2164 *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 );
2165
2166 /* execute parity fix in constant time */
2167 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002168 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002169 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) );
2170
2171 /* actual scalar recoding */
2172 ecp_comb_recode_core( k, d, w, &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002173
2174cleanup:
2175 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002176 mbedtls_mpi_free( &M );
Manuel Pégourié-Gonnardec5606a2017-03-09 12:46:45 +01002177
2178 return( ret );
2179}
2180
2181/*
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002182 * Perform comb multiplication (for short Weierstrass curves)
2183 * once the auxiliary table has been pre-computed.
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002184 *
2185 * Scalar recoding may use a parity trick that makes us compute -m * P,
2186 * if that is the case we'll need to recover m * P at the end.
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002187 */
2188static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
2189 mbedtls_ecp_point *R,
2190 const mbedtls_mpi *m,
2191 const mbedtls_ecp_point *T,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002192 unsigned char T_size,
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002193 unsigned char w,
2194 size_t d,
2195 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002196 void *p_rng,
2197 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002198{
2199 int ret;
Manuel Pégourié-Gonnard62738e92017-03-14 10:00:21 +01002200 unsigned char parity_trick;
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002201 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002202 mbedtls_ecp_point *RR = R;
2203
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002204#if defined(MBEDTLS_ECP_RESTARTABLE)
2205 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2206 {
2207 RR = &rs_ctx->rsm->R;
2208
2209 if( rs_ctx->rsm->state == ecp_rsm_final_norm )
2210 goto final_norm;
2211 }
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002212#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002213
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002214 MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w,
2215 &parity_trick ) );
2216 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d,
2217 f_rng, p_rng, rs_ctx ) );
2218 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) );
2219
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002220#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002221 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002222 rs_ctx->rsm->state = ecp_rsm_final_norm;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002223
Manuel Pégourié-Gonnard4ed1dab2017-08-24 11:02:04 +02002224final_norm:
Manuel Pégourié-Gonnard18b0b3c2020-06-08 09:53:20 +02002225 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002226#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002227 /*
2228 * Knowledge of the jacobian coordinates may leak the last few bits of the
2229 * scalar [1], and since our MPI implementation isn't constant-flow,
2230 * inversion (used for coordinate normalization) may leak the full value
2231 * of its input via side-channels [2].
2232 *
2233 * [1] https://eprint.iacr.org/2003/191
2234 * [2] https://eprint.iacr.org/2020/055
2235 *
2236 * Avoid the leak by randomizing coordinates before we normalize them.
2237 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002238#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002239 if( f_rng != 0 )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002240#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002241 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
2242
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002243 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
2244
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002245#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard28d16282017-08-23 17:33:27 +02002246 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2247 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) );
Manuel Pégourié-Gonnard8962ddb2017-03-14 12:11:21 +01002248#endif
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002249
2250cleanup:
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002251 return( ret );
2252}
2253
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002254/*
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002255 * Pick window size based on curve size and whether we optimize for base point
2256 */
2257static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
2258 unsigned char p_eq_g )
2259{
2260 unsigned char w;
2261
2262 /*
2263 * Minimize the number of multiplications, that is minimize
2264 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
2265 * (see costs of the various parts, with 1S = 1M)
2266 */
2267 w = grp->nbits >= 384 ? 5 : 4;
2268
2269 /*
2270 * If P == G, pre-compute a bit more, since this may be re-used later.
2271 * Just adding one avoids upping the cost of the first mul too much,
2272 * and the memory cost too.
2273 */
2274 if( p_eq_g )
2275 w++;
2276
2277 /*
2278 * Make sure w is within bounds.
2279 * (The last test is useful only for very small curves in the test suite.)
2280 */
2281 if( w > MBEDTLS_ECP_WINDOW_SIZE )
2282 w = MBEDTLS_ECP_WINDOW_SIZE;
2283 if( w >= grp->nbits )
2284 w = 2;
2285
2286 return( w );
2287}
2288
2289/*
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002290 * Multiplication using the comb method - for curves in short Weierstrass form
2291 *
2292 * This function is mainly responsible for administrative work:
2293 * - managing the restart context if enabled
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002294 * - managing the table of precomputed points (passed between the below two
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002295 * functions): allocation, computation, ownership tranfer, freeing.
2296 *
2297 * It delegates the actual arithmetic work to:
2298 * ecp_precompute_comb() and ecp_mul_comb_with_precomp()
2299 *
2300 * See comments on ecp_comb_recode_core() regarding the computation strategy.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002302static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2303 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002304 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002305 void *p_rng,
2306 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002307{
2308 int ret;
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002309 unsigned char w, p_eq_g, i;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01002310 size_t d;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002311 unsigned char T_size = 0, T_ok = 0;
2312 mbedtls_ecp_point *T = NULL;
2313#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2314 ecp_drbg_context drbg_ctx;
2315
2316 ecp_drbg_init( &drbg_ctx );
2317#endif
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002318
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002319 ECP_RS_ENTER( rsm );
Manuel Pégourié-Gonnard510d5ca2017-03-08 11:41:47 +01002320
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002321#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2322 if( f_rng == NULL )
2323 {
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002324 /* Adjust pointers */
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002325 f_rng = &ecp_drbg_random;
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002326#if defined(MBEDTLS_ECP_RESTARTABLE)
2327 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2328 p_rng = &rs_ctx->rsm->drbg_ctx;
2329 else
2330#endif
2331 p_rng = &drbg_ctx;
2332
2333 /* Initialize internal DRBG if necessary */
2334#if defined(MBEDTLS_ECP_RESTARTABLE)
2335 if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
2336 rs_ctx->rsm->drbg_seeded == 0 )
2337#endif
2338 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002339 const size_t m_len = ( grp->nbits + 7 ) / 8;
2340 MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
Manuel Pégourié-Gonnard047986c2020-06-04 09:43:14 +02002341 }
2342#if defined(MBEDTLS_ECP_RESTARTABLE)
2343 if( rs_ctx != NULL && rs_ctx->rsm != NULL )
2344 rs_ctx->rsm->drbg_seeded = 1;
2345#endif
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002346 }
2347#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2348
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002349 /* Is P the base point ? */
2350#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
2351 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
2352 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard196d1332017-08-28 13:14:27 +02002353#else
2354 p_eq_g = 0;
Manuel Pégourié-Gonnard22be6352017-03-09 13:02:35 +01002355#endif
2356
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002357 /* Pick window size and deduce related sizes */
Manuel Pégourié-Gonnard4b2336d2017-03-09 13:23:50 +01002358 w = ecp_pick_window_size( grp, p_eq_g );
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002359 T_size = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002360 d = ( grp->nbits + w - 1 ) / w;
2361
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002362 /* Pre-computed table: do we have it already for the base point? */
2363 if( p_eq_g && grp->T != NULL )
2364 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002365 /* second pointer to the same table, will be deleted on exit */
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002366 T = grp->T;
2367 T_ok = 1;
2368 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002369 else
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002370#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002371 /* Pre-computed table: do we have one in progress? complete? */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002372 if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL )
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002373 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002374 /* transfer ownership of T from rsm to local function */
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002375 T = rs_ctx->rsm->T;
2376 rs_ctx->rsm->T = NULL;
2377 rs_ctx->rsm->T_size = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002378
Manuel Pégourié-Gonnardb25cb602018-10-16 11:48:09 +02002379 /* This effectively jumps to the call to mul_comb_after_precomp() */
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002380 T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002381 }
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002382 else
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002383#endif
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002384 /* Allocate table if we didn't have any */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002385 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002386 T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002387 if( T == NULL )
2388 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02002389 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002390 goto cleanup;
2391 }
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +02002392
2393 for( i = 0; i < T_size; i++ )
2394 mbedtls_ecp_point_init( &T[i] );
Manuel Pégourié-Gonnard11556e22017-08-24 13:41:19 +02002395
2396 T_ok = 0;
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002397 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002398
Manuel Pégourié-Gonnard085b1df2017-03-16 16:56:04 +01002399 /* Compute table (or finish computing it) if not done already */
2400 if( !T_ok )
2401 {
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002402 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002403
2404 if( p_eq_g )
2405 {
Manuel Pégourié-Gonnard7037e222017-08-23 14:30:36 +02002406 /* almost transfer ownership of T to the group, but keep a copy of
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +02002407 * the pointer to use for calling the next function more easily */
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002408 grp->T = T;
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002409 grp->T_size = T_size;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002410 }
2411 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002412
Manuel Pégourié-Gonnard391f4412017-03-13 12:26:21 +01002413 /* Actual comb multiplication using precomputed points */
2414 MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m,
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002415 T, T_size, w, d,
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002416 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002417
2418cleanup:
2419
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002420#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2421 ecp_drbg_free( &drbg_ctx );
2422#endif
2423
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002424 /* does T belong to the group? */
2425 if( T == grp->T )
2426 T = NULL;
2427
2428 /* does T belong to the restart context? */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002429#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002430 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 +01002431 {
Manuel Pégourié-Gonnard45fd0162017-03-22 08:24:42 +01002432 /* transfer ownership of T from local function to rsm */
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002433 rs_ctx->rsm->T_size = T_size;
Manuel Pégourié-Gonnard3cade222017-04-20 09:31:00 +02002434 rs_ctx->rsm->T = T;
Manuel Pégourié-Gonnardc9c0aa62017-03-16 14:53:26 +01002435 T = NULL;
2436 }
2437#endif
2438
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002439 /* did T belong to us? then let's destroy it! */
2440 if( T != NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002441 {
Manuel Pégourié-Gonnard92cceb22017-08-23 16:27:29 +02002442 for( i = 0; i < T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002443 mbedtls_ecp_point_free( &T[i] );
2444 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002445 }
2446
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002447 /* don't free R while in progress in case R == P */
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002448#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard2fad7ae2017-03-14 13:13:13 +01002449 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
2450#endif
Manuel Pégourié-Gonnard07bf6f52017-03-16 17:21:38 +01002451 /* prevent caller from using invalid value */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01002452 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002453 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002454
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002455 ECP_RS_LEAVE( rsm );
Manuel Pégourié-Gonnard77af79a2017-03-14 10:58:00 +01002456
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002457 return( ret );
2458}
2459
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002460#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002461
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002462#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002463/*
2464 * For Montgomery curves, we do all the internal arithmetic in projective
2465 * coordinates. Import/export of points uses only the x coordinates, which is
2466 * internaly represented as X / Z.
2467 *
2468 * For scalar multiplication, we'll use a Montgomery ladder.
2469 */
2470
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01002471/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002472 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
2473 * Cost: 1M + 1I
2474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002476{
2477 int ret;
2478
Janos Follathb0697532016-08-18 12:38:46 +01002479#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002480 if( mbedtls_internal_ecp_grp_capable( grp ) )
2481 return( mbedtls_internal_ecp_normalize_mxz( grp, P ) );
Janos Follath372697b2016-10-28 16:53:11 +01002482#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
2485 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
2486 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002487
2488cleanup:
2489 return( ret );
2490}
2491
2492/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002493 * Randomize projective x/z coordinates:
2494 * (X, Z) -> (l X, l Z) for random l
2495 * This is sort of the reverse operation of ecp_normalize_mxz().
2496 *
2497 * This countermeasure was first suggested in [2].
2498 * Cost: 2M
2499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002500static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002501 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2502{
2503 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002504 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01002505 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002506 int count = 0;
2507
Janos Follathb0697532016-08-18 12:38:46 +01002508#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002509 if( mbedtls_internal_ecp_grp_capable( grp ) )
2510 return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follath372697b2016-10-28 16:53:11 +01002511#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002512
2513 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002515
2516 /* Generate l such that 1 < l < p */
2517 do
2518 {
Ron Eldorca6ff582017-01-12 14:50:50 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
2522 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002523
2524 if( count++ > 10 )
Jonas6645fd32020-05-08 16:57:18 +09002525 {
2526 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
2527 goto cleanup;
2528 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002529 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002531
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
2533 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 +01002534
2535cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002536 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002537
2538 return( ret );
2539}
2540
2541/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002542 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
2543 * for Montgomery curves in x/z coordinates.
2544 *
2545 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
2546 * with
2547 * d = X1
2548 * P = (X2, Z2)
2549 * Q = (X3, Z3)
2550 * R = (X4, Z4)
2551 * S = (X5, Z5)
2552 * and eliminating temporary variables tO, ..., t4.
2553 *
2554 * Cost: 5M + 4S
2555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
2557 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
2558 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
2559 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002560{
2561 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002563
Janos Follathb0697532016-08-18 12:38:46 +01002564#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002565 if( mbedtls_internal_ecp_grp_capable( grp ) )
2566 return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) );
Janos Follath372697b2016-10-28 16:53:11 +01002567#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01002568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
2570 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
2571 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002573 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
2574 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
2575 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
2576 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
2577 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
2578 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
2579 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
2580 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
2581 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
2582 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
2583 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
2584 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
2585 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
2586 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
2587 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
2588 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
2589 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
2590 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 +01002591
2592cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
2594 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
2595 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002596
2597 return( ret );
2598}
2599
2600/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002601 * Multiplication with Montgomery ladder in x/z coordinates,
2602 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002603 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2605 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002606 int (*f_rng)(void *, unsigned char *, size_t),
2607 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002608{
2609 int ret;
2610 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002611 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002612 mbedtls_ecp_point RP;
2613 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002614#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2615 ecp_drbg_context drbg_ctx;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002616
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002617 ecp_drbg_init( &drbg_ctx );
2618#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002620
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002621#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2622 if( f_rng == NULL )
2623 {
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02002624 const size_t m_len = ( grp->nbits + 7 ) / 8;
2625 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002626 f_rng = &ecp_drbg_random;
2627 p_rng = &drbg_ctx;
2628 }
2629#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2630
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002631 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002632 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
2633 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002634
2635 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002636 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
2637 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
2638 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002639
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01002640 /* RP.X might be sligtly larger than P, so reduce it */
2641 MOD_ADD( RP.X );
2642
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01002643 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002644#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01002645 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002646#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002647 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002648
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002649 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002650 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002651 while( i-- > 0 )
2652 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002653 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01002654 /*
2655 * if (b) R = 2R + P else R = 2R,
2656 * which is:
2657 * if (b) double_add( RP, R, RP, R )
2658 * else double_add( R, RP, R, RP )
2659 * but using safe conditional swaps to avoid leaks
2660 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002661 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 ) );
2663 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
2664 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
2665 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002666 }
2667
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002668 /*
2669 * Knowledge of the projective coordinates may leak the last few bits of the
2670 * scalar [1], and since our MPI implementation isn't constant-flow,
2671 * inversion (used for coordinate normalization) may leak the full value
2672 * of its input via side-channels [2].
2673 *
2674 * [1] https://eprint.iacr.org/2003/191
2675 * [2] https://eprint.iacr.org/2020/055
2676 *
2677 * Avoid the leak by randomizing coordinates before we normalize them.
2678 */
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002679#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002680 if( f_rng != NULL )
Manuel Pégourié-Gonnardc334f412020-06-04 10:43:29 +02002681#endif
Manuel Pégourié-Gonnardf6004162020-03-25 12:41:29 +01002682 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
2683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002684 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002685
2686cleanup:
Manuel Pégourié-Gonnardd18f0512020-06-03 12:11:56 +02002687#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2688 ecp_drbg_free( &drbg_ctx );
2689#endif
2690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002691 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002692
2693 return( ret );
2694}
2695
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002696#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01002697
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01002698/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002699 * Restartable multiplication R = m * P
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002700 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002701int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002702 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002703 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
2704 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002705{
Janos Follathb0697532016-08-18 12:38:46 +01002706 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00002707#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2708 char is_grp_capable = 0;
2709#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002710 ECP_VALIDATE_RET( grp != NULL );
2711 ECP_VALIDATE_RET( R != NULL );
2712 ECP_VALIDATE_RET( m != NULL );
2713 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002714
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002715#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002716 /* reset ops count for this call if top-level */
2717 if( rs_ctx != NULL && rs_ctx->depth++ == 0 )
2718 rs_ctx->ops_done = 0;
2719#endif
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002720
Janos Follathc44ab972016-11-18 16:38:23 +00002721#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002722 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
Janos Follathc44ab972016-11-18 16:38:23 +00002723 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathc44ab972016-11-18 16:38:23 +00002724#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002725
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002726#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002727 /* skip argument check when restarting */
Manuel Pégourié-Gonnard95aedfe2017-08-24 13:47:04 +02002728 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002729#endif
2730 {
Manuel Pégourié-Gonnard5314f232017-04-21 12:36:59 +02002731 /* check_privkey is free */
2732 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK );
2733
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002734 /* Common sanity checks */
2735 MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) );
2736 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) );
Manuel Pégourié-Gonnarda08cd1a2017-04-20 11:29:43 +02002737 }
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002738
2739 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002740#if defined(ECP_MONTGOMERY)
2741 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002742 MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) );
Janos Follath430d3372016-11-03 14:25:37 +00002743#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002744#if defined(ECP_SHORTWEIERSTRASS)
2745 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002746 MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) );
Janos Follath430d3372016-11-03 14:25:37 +00002747#endif
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002748
Janos Follath6c8ccd52016-11-29 15:37:09 +00002749cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002750
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002751#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002752 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002753 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002754#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002755
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002756#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard3a256122017-04-20 11:20:26 +02002757 if( rs_ctx != NULL )
2758 rs_ctx->depth--;
2759#endif
2760
Janos Follathb0697532016-08-18 12:38:46 +01002761 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002762}
2763
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002764/*
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002765 * Multiplication R = m * P
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002766 */
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002767int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002768 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002769 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002770{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002771 ECP_VALIDATE_RET( grp != NULL );
2772 ECP_VALIDATE_RET( R != NULL );
2773 ECP_VALIDATE_RET( m != NULL );
2774 ECP_VALIDATE_RET( P != NULL );
Manuel Pégourié-Gonnard884569c2017-04-20 10:10:59 +02002775 return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002776}
Manuel Pégourié-Gonnardb739a712017-04-19 10:11:56 +02002777
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002778#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002779/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002780 * Check that an affine point is valid as a public key,
2781 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002782 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002783static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002784{
2785 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002786 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002787
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002788 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002789 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2790 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2791 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2792 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2793 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002795 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002796
2797 /*
2798 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002799 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002800 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002801 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2802 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002803
2804 /* Special case for A = -3 */
2805 if( grp->A.p == NULL )
2806 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002807 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002808 }
2809 else
2810 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002811 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002812 }
2813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002814 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2815 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002816
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002817 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2818 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002819
2820cleanup:
2821
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002822 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002823
2824 return( ret );
2825}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002826#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002827
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002828/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002829 * R = m * P with shortcuts for m == 1 and m == -1
2830 * NOT constant-time - ONLY for short Weierstrass!
2831 */
2832static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2833 mbedtls_ecp_point *R,
2834 const mbedtls_mpi *m,
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002835 const mbedtls_ecp_point *P,
2836 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002837{
2838 int ret;
2839
2840 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2841 {
2842 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2843 }
2844 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2845 {
2846 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2847 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2848 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2849 }
2850 else
2851 {
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002852 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P,
2853 NULL, NULL, rs_ctx ) );
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002854 }
2855
2856cleanup:
2857 return( ret );
2858}
2859
2860/*
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002861 * Restartable linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002862 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002863 */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002864int mbedtls_ecp_muladd_restartable(
2865 mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002866 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002867 const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
2868 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002869{
2870 int ret;
2871 mbedtls_ecp_point mP;
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002872 mbedtls_ecp_point *pmP = &mP;
2873 mbedtls_ecp_point *pR = R;
Janos Follathc44ab972016-11-18 16:38:23 +00002874#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2875 char is_grp_capable = 0;
2876#endif
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002877 ECP_VALIDATE_RET( grp != NULL );
2878 ECP_VALIDATE_RET( R != NULL );
2879 ECP_VALIDATE_RET( m != NULL );
2880 ECP_VALIDATE_RET( P != NULL );
2881 ECP_VALIDATE_RET( n != NULL );
2882 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002883
2884 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2885 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2886
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002887 mbedtls_ecp_point_init( &mP );
2888
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002889 ECP_RS_ENTER( ma );
2890
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002891#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002892 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2893 {
2894 /* redirect intermediate results to restart context */
2895 pmP = &rs_ctx->ma->mP;
2896 pR = &rs_ctx->ma->R;
2897
2898 /* jump to next operation */
2899 if( rs_ctx->ma->state == ecp_rsma_mul2 )
2900 goto mul2;
2901 if( rs_ctx->ma->state == ecp_rsma_add )
2902 goto add;
2903 if( rs_ctx->ma->state == ecp_rsma_norm )
2904 goto norm;
2905 }
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002906#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002907
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002908 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002909#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002910 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002911 rs_ctx->ma->state = ecp_rsma_mul2;
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002912
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002913mul2:
2914#endif
2915 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) );
Janos Follathaf6f2692018-12-07 09:55:24 +00002916
2917#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2918 if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) )
2919 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
2920#endif /* MBEDTLS_ECP_INTERNAL_ALT */
2921
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002922#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002923 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002924 rs_ctx->ma->state = ecp_rsma_add;
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002925
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002926add:
2927#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002928 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002929 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) );
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002930#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002931 if( rs_ctx != NULL && rs_ctx->ma != NULL )
Manuel Pégourié-Gonnardc9efa002017-08-24 10:25:06 +02002932 rs_ctx->ma->state = ecp_rsma_norm;
Janos Follath430d3372016-11-03 14:25:37 +00002933
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002934norm:
2935#endif
Manuel Pégourié-Gonnardc7511482017-04-20 16:31:00 +02002936 MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002937 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) );
2938
Manuel Pégourié-Gonnard4b9c51e2017-04-20 15:50:26 +02002939#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002940 if( rs_ctx != NULL && rs_ctx->ma != NULL )
2941 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) );
2942#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002943
2944cleanup:
Janos Follathc44ab972016-11-18 16:38:23 +00002945#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Manuel Pégourié-Gonnardebac5d32017-08-23 16:23:36 +02002946 if( is_grp_capable )
Janos Follathc44ab972016-11-18 16:38:23 +00002947 mbedtls_internal_ecp_free( grp );
Janos Follathc44ab972016-11-18 16:38:23 +00002948#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard1631d632017-04-20 14:48:56 +02002949
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002950 mbedtls_ecp_point_free( &mP );
2951
Manuel Pégourié-Gonnarddb4a8eb2017-08-23 18:18:22 +02002952 ECP_RS_LEAVE( ma );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002953
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002954 return( ret );
2955}
2956
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002957/*
2958 * Linear combination
2959 * NOT constant-time
2960 */
2961int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2962 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2963 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2964{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002965 ECP_VALIDATE_RET( grp != NULL );
2966 ECP_VALIDATE_RET( R != NULL );
2967 ECP_VALIDATE_RET( m != NULL );
2968 ECP_VALIDATE_RET( P != NULL );
2969 ECP_VALIDATE_RET( n != NULL );
2970 ECP_VALIDATE_RET( Q != NULL );
Manuel Pégourié-Gonnard54dd6522017-04-20 13:36:18 +02002971 return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) );
2972}
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002973
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002974#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002975/*
2976 * Check validity of a public key for Montgomery curves with x-only schemes
2977 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002978static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002979{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002980 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00002981 /* Allow any public value, if it's too big then we'll just reduce it mod p
2982 * (RFC 7748 sec. 5 para. 3). */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002983 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2984 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002985
2986 return( 0 );
2987}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002988#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002989
2990/*
2991 * Check that a point is valid as a public key
2992 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002993int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
2994 const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002995{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00002996 ECP_VALIDATE_RET( grp != NULL );
2997 ECP_VALIDATE_RET( pt != NULL );
2998
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002999 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003000 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
3001 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003002
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003003#if defined(ECP_MONTGOMERY)
3004 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003005 return( ecp_check_pubkey_mx( grp, pt ) );
3006#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003007#if defined(ECP_SHORTWEIERSTRASS)
3008 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003009 return( ecp_check_pubkey_sw( grp, pt ) );
3010#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003011 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003012}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003013
3014/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003015 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003016 */
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003017int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp,
3018 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003019{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003020 ECP_VALIDATE_RET( grp != NULL );
3021 ECP_VALIDATE_RET( d != NULL );
3022
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003023#if defined(ECP_MONTGOMERY)
3024 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003025 {
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003026 /* see RFC 7748 sec. 5 para. 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003027 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
3028 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003029 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003030 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003031
3032 /* see [Curve25519] page 5 */
3033 if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 )
3034 return( MBEDTLS_ERR_ECP_INVALID_KEY );
3035
3036 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003037 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003038#endif /* ECP_MONTGOMERY */
3039#if defined(ECP_SHORTWEIERSTRASS)
3040 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003041 {
3042 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003043 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
3044 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
3045 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003046 else
3047 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01003048 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003049#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003051 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02003052}
3053
3054/*
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003055 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003056 */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003057int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
3058 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003059 int (*f_rng)(void *, unsigned char *, size_t),
3060 void *p_rng )
3061{
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003062 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003063 size_t n_size;
3064
3065 ECP_VALIDATE_RET( grp != NULL );
3066 ECP_VALIDATE_RET( d != NULL );
3067 ECP_VALIDATE_RET( f_rng != NULL );
3068
3069 n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003070
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003071#if defined(ECP_MONTGOMERY)
3072 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003073 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003074 /* [M225] page 5 */
3075 size_t b;
3076
Janos Follath98e28a72016-05-31 14:03:54 +01003077 do {
3078 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
3079 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003080
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003081 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02003082 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003083 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003084 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003085 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003086 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003087
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003088 /* Make sure the last two bits are unset for Curve448, three bits for
3089 Curve25519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003090 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
3091 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
Nicholas Wilson08f3ef12015-11-10 13:10:01 +00003092 if( grp->nbits == 254 )
3093 {
3094 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
3095 }
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003096 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003097#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003098
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003099#if defined(ECP_SHORTWEIERSTRASS)
3100 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003101 {
3102 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01003103 int count = 0;
Janos Follath867a3ab2019-10-11 14:21:53 +01003104 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01003105
3106 /*
3107 * Match the procedure given in RFC 6979 (deterministic ECDSA):
3108 * - use the same byte ordering;
3109 * - keep the leftmost nbits bits of the generated octet string;
3110 * - try until result is in the desired range.
3111 * This also avoids any biais, which is especially important for ECDSA.
3112 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003113 do
3114 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01003115 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003116 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003117
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01003118 /*
3119 * Each try has at worst a probability 1/2 of failing (the msb has
3120 * a probability 1/2 of being 0, and then the result will be < N),
3121 * so after 30 tries failure probability is a most 2**(-30).
3122 *
3123 * For most curves, 1 try is enough with overwhelming probability,
3124 * since N starts with a lot of 1s in binary, but some curves
3125 * such as secp224k1 are actually very close to the worst case.
3126 */
Manuel Pégourié-Gonnard67543962017-04-21 13:19:43 +02003127 if( ++count > 30 )
3128 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath4c3408b2019-09-16 14:27:39 +01003129
Janos Follath867a3ab2019-10-11 14:21:53 +01003130 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath4c3408b2019-09-16 14:27:39 +01003131 if( ret != 0 )
3132 {
3133 goto cleanup;
3134 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003135 }
Janos Follath867a3ab2019-10-11 14:21:53 +01003136 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01003137 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02003138#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003139
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003140cleanup:
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003141 return( ret );
3142}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01003143
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003144/*
3145 * Generate a keypair with configurable base point
3146 */
3147int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
3148 const mbedtls_ecp_point *G,
3149 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3150 int (*f_rng)(void *, unsigned char *, size_t),
3151 void *p_rng )
3152{
3153 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003154 ECP_VALIDATE_RET( grp != NULL );
3155 ECP_VALIDATE_RET( d != NULL );
3156 ECP_VALIDATE_RET( G != NULL );
3157 ECP_VALIDATE_RET( Q != NULL );
3158 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnarda7937f92017-04-20 15:37:46 +02003159
3160 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
3161 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
3162
3163cleanup:
3164 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003165}
3166
3167/*
3168 * Generate key pair, wrapper for conventional base point
3169 */
3170int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
3171 mbedtls_mpi *d, mbedtls_ecp_point *Q,
3172 int (*f_rng)(void *, unsigned char *, size_t),
3173 void *p_rng )
3174{
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003175 ECP_VALIDATE_RET( grp != NULL );
3176 ECP_VALIDATE_RET( d != NULL );
3177 ECP_VALIDATE_RET( Q != NULL );
3178 ECP_VALIDATE_RET( f_rng != NULL );
3179
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02003180 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01003181}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01003182
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003183/*
3184 * Generate a keypair, prettier wrapper
3185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003186int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003187 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
3188{
3189 int ret;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003190 ECP_VALIDATE_RET( key != NULL );
3191 ECP_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003192
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003193 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003194 return( ret );
3195
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003196 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01003197}
3198
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003199/*
3200 * Check a public-private key pair
3201 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003202int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003203{
3204 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003205 mbedtls_ecp_point Q;
3206 mbedtls_ecp_group grp;
Hanno Becker4f8e8e52018-12-14 15:08:03 +00003207 ECP_VALIDATE_RET( pub != NULL );
3208 ECP_VALIDATE_RET( prv != NULL );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003210 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003211 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003212 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
3213 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
3214 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003215 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003216 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003217 }
3218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003219 mbedtls_ecp_point_init( &Q );
3220 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003221
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003222 /* mbedtls_ecp_mul() needs a non-const group... */
3223 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003224
3225 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003226 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003228 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
3229 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
3230 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003231 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003232 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003233 goto cleanup;
3234 }
3235
3236cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003237 mbedtls_ecp_point_free( &Q );
3238 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01003239
3240 return( ret );
3241}
3242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003243#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003244
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003245#if defined(ECP_ONE_STEP_KDF)
3246/*
3247 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
3248 * but unofficial ones can be found at:
3249 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
3250 *
3251 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003252 * 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 +02003253 * less than one block).
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003254 */
3255#if defined(MBEDTLS_SHA512_C)
3256
3257static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003258 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
3259 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003260};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003261static const uint8_t test_kdf_out[40] = {
3262 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
3263 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
3264 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
3265 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
3266 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003267};
3268
3269#elif defined(MBEDTLS_SHA256_C)
3270
3271static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003272 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
3273 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003274};
Manuel Pégourié-Gonnard2df14232020-06-22 10:18:58 +02003275static const uint8_t test_kdf_out[40] = {
3276 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
3277 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
3278 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
3279 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
3280 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003281};
3282
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003283#endif
3284
3285static int ecp_kdf_self_test( void )
3286{
3287 int ret;
3288 ecp_drbg_context kdf_ctx;
3289 mbedtls_mpi scalar;
3290 uint8_t out[sizeof( test_kdf_out )];
3291
3292 ecp_drbg_init( &kdf_ctx );
3293 mbedtls_mpi_init( &scalar );
3294 memset( out, 0, sizeof( out ) );
3295
3296 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
3297 test_kdf_z, sizeof( test_kdf_z ) ) );
3298
3299 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
3300 &scalar, sizeof( test_kdf_z ) ) );
3301
3302 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
3303
3304 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
3305 ret = -1;
3306
3307cleanup:
3308 ecp_drbg_free( &kdf_ctx );
3309 mbedtls_mpi_free( &scalar );
3310
3311 return( ret );
3312}
3313#endif /* ECP_ONE_STEP_KDF */
3314
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01003315/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003316 * Checkup routine
3317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003318int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003319{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003320 int ret;
3321 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003322 mbedtls_ecp_group grp;
3323 mbedtls_ecp_point R, P;
3324 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003325 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003326 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02003327 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003328 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003329 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003330 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01003331 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01003332 "400000000000000000000000000000000000000000000000", /* one and zeros */
3333 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
3334 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003335 };
3336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003337 mbedtls_ecp_group_init( &grp );
3338 mbedtls_ecp_point_init( &R );
3339 mbedtls_ecp_point_init( &P );
3340 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003341
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003342 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003343#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003344 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02003345#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02003346 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02003347#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003348
3349 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003350 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003351
3352 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003353 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
3354 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003355
3356 add_count = 0;
3357 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003358 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003359 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3360 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003361
3362 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3363 {
3364 add_c_prev = add_count;
3365 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003366 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003367 add_count = 0;
3368 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003369 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003371 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3372 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003373
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003374 if( add_count != add_c_prev ||
3375 dbl_count != dbl_c_prev ||
3376 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003377 {
3378 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003379 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003380
3381 ret = 1;
3382 goto cleanup;
3383 }
3384 }
3385
3386 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003387 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003388
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003389 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003390 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003391 /* We computed P = 2G last time, use it */
3392
3393 add_count = 0;
3394 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003395 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003396 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
3397 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003398
3399 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
3400 {
3401 add_c_prev = add_count;
3402 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003403 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003404 add_count = 0;
3405 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003406 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003408 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
3409 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003410
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01003411 if( add_count != add_c_prev ||
3412 dbl_count != dbl_c_prev ||
3413 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003414 {
3415 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003416 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003417
3418 ret = 1;
3419 goto cleanup;
3420 }
3421 }
3422
3423 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003424 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02003425
Manuel Pégourié-Gonnard72177e32020-06-16 12:51:42 +02003426#if defined(ECP_ONE_STEP_KDF)
3427 if( verbose != 0 )
3428 mbedtls_printf( " ECP test #3 (internal KDF): " );
3429
3430 ret = ecp_kdf_self_test();
3431 if( ret != 0 )
3432 {
3433 if( verbose != 0 )
3434 mbedtls_printf( "failed\n" );
3435
3436 ret = 1;
3437 goto cleanup;
3438 }
3439
3440 if( verbose != 0 )
3441 mbedtls_printf( "passed\n" );
3442#endif /* ECP_ONE_STEP_KDF */
3443
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003444cleanup:
3445
3446 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003447 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003449 mbedtls_ecp_group_free( &grp );
3450 mbedtls_ecp_point_free( &R );
3451 mbedtls_ecp_point_free( &P );
3452 mbedtls_mpi_free( &m );
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( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01003456
3457 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003458}
3459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003460#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003461
Janos Follathb0697532016-08-18 12:38:46 +01003462#endif /* !MBEDTLS_ECP_ALT */
3463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02003464#endif /* MBEDTLS_ECP_C */