blob: f83f4db7a0bcfaeccb7c6fa815e94ffd8053853b [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úti4e9f7122020-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úti4e9f7122020-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
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020056 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020057 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010058 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020059 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020060 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
61 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
62 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010063 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020064 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010065 * render ECC resistant against Side Channel Attacks. IACR Cryptology
66 * ePrint Archive, 2004, vol. 2004, p. 342.
67 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010068 */
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020072#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020074#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010077
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000078#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000079#include "mbedtls/threading.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020080
Rich Evans00ab4702015-02-06 13:43:58 +000081#include <string.h>
82
Janos Follathb0697532016-08-18 12:38:46 +010083#if !defined(MBEDTLS_ECP_ALT)
84
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000086#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020087#else
Rich Evans00ab4702015-02-06 13:43:58 +000088#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000089#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020091#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020093#endif
94
Janos Follath47d28f02016-11-01 13:22:05 +000095#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +010096
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020097#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020098#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020099#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200100#elif defined(MBEDTLS_CTR_DRBG_C)
101#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200102#elif defined(MBEDTLS_SHA512_C)
103#include "mbedtls/sha512.h"
104#elif defined(MBEDTLS_SHA256_C)
105#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200106#else
107#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
108#endif
109#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
110
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100111#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
112 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100113#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200114#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100115
Paul Bakker34617722014-06-13 17:20:13 +0200116/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +0200118 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
119}
120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100122/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100123 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200124 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100125 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100126static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100127#endif
128
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200129#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
130/*
131 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200132 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200133 * that people will pass non-NULL RNG when they care about side-channels, but
134 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
135 * no opportunity for the user to do anything about it.
136 *
137 * The obvious strategies for addressing that include:
138 * - change those APIs so that they take RNG arguments;
139 * - require a global RNG to be available to all crypto modules.
140 *
141 * Unfortunately those would break compatibility. So what we do instead is
142 * have our own internal DRBG instance, seeded from the secret scalar.
143 *
144 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200145 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200146 */
147
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200148#if defined(MBEDTLS_HMAC_DRBG_C)
149
150/* DRBG context type */
151typedef mbedtls_hmac_drbg_context ecp_drbg_context;
152
153/* DRBG context init */
154static inline void ecp_drbg_init( ecp_drbg_context *ctx )
155{
156 mbedtls_hmac_drbg_init( ctx );
157}
158
159/* DRBG context free */
160static inline void ecp_drbg_free( ecp_drbg_context *ctx )
161{
162 mbedtls_hmac_drbg_free( ctx );
163}
164
165/* DRBG function */
166static inline int ecp_drbg_random( void *p_rng,
167 unsigned char *output, size_t output_len )
168{
169 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
170}
171
172/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200173static int ecp_drbg_seed( ecp_drbg_context *ctx,
174 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200175{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200176 int ret;
177 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200178 /* The list starts with strong hashes */
179 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
180 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
181
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200182 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
183 secret_bytes, secret_len ) );
184
185 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
186
187cleanup:
188 mbedtls_zeroize( secret_bytes, secret_len );
189
190 return( ret );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200191}
192
193#elif defined(MBEDTLS_CTR_DRBG_C)
194
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200195/* DRBG context type */
196typedef mbedtls_ctr_drbg_context ecp_drbg_context;
197
198/* DRBG context init */
199static inline void ecp_drbg_init( ecp_drbg_context *ctx )
200{
201 mbedtls_ctr_drbg_init( ctx );
202}
203
204/* DRBG context free */
205static inline void ecp_drbg_free( ecp_drbg_context *ctx )
206{
207 mbedtls_ctr_drbg_free( ctx );
208}
209
210/* DRBG function */
211static inline int ecp_drbg_random( void *p_rng,
212 unsigned char *output, size_t output_len )
213{
214 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
215}
216
217/*
218 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
219 * we need to pass an entropy function when seeding. So we use a dummy
220 * function for that, and pass the actual entropy as customisation string.
221 * (During seeding of CTR_DRBG the entropy input and customisation string are
222 * concatenated before being used to update the secret state.)
223 */
224static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
225{
226 (void) ctx;
227 memset( out, 0, len );
228 return( 0 );
229}
230
231/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200232static int ecp_drbg_seed( ecp_drbg_context *ctx,
233 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200234{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200235 int ret;
236 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200237
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200238 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
239 secret_bytes, secret_len ) );
240
241 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
242 secret_bytes, secret_len );
243
244cleanup:
245 mbedtls_zeroize( secret_bytes, secret_len );
246
247 return( ret );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200248}
249
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200250#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200251
252/* This will be used in the self-test function */
253#define ECP_ONE_STEP_KDF
254
255/*
256 * We need to expand secret data (the scalar) into a longer stream of bytes.
257 *
258 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
259 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
260 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
261 *
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200262 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200263 */
264#if defined(MBEDTLS_SHA512_C)
265
266#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
267#define HASH_BLOCK_BYTES ( 512 / 8 )
268
269#elif defined(MBEDTLS_SHA256_C)
270
271#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
272#define HASH_BLOCK_BYTES ( 256 / 8 )
273
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200274#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200275
276/*
277 * State consists of a 32-bit counter plus the secret value.
278 *
279 * We stored them concatenated in a single buffer as that's what will get
280 * passed to the hash function.
281 */
282typedef struct {
283 size_t total_len;
284 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
285} ecp_drbg_context;
286
287static void ecp_drbg_init( ecp_drbg_context *ctx )
288{
289 memset( ctx, 0, sizeof( ecp_drbg_context ) );
290}
291
292static void ecp_drbg_free( ecp_drbg_context *ctx )
293{
294 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
295}
296
297static int ecp_drbg_seed( ecp_drbg_context *ctx,
298 const mbedtls_mpi *secret, size_t secret_len )
299{
300 ctx->total_len = 4 + secret_len;
301 memset( ctx->buf, 0, 4);
302 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
303}
304
305static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
306{
307 ecp_drbg_context *ctx = p_rng;
308 int ret;
309 size_t len_done = 0;
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200310 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200311
312 while( len_done < output_len )
313 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200314 uint8_t use_len;
315
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200316 /* This function is only called for coordinate randomisation, which
317 * happens only twice in a scalar multiplication. Each time needs a
318 * random value in the range [2, p-1], and gets it by drawing len(p)
319 * bytes from this function, and retrying up to 10 times if unlucky.
320 *
321 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200322 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
323 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200324 *
325 * Since we don't need to draw more that 255 blocks, don't bother
326 * with carry propagation and just return an error instead. We can
327 * change that it we even need to draw more blinding values.
328 */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200329 ctx->buf[3] += 1;
330 if( ctx->buf[3] == 0 )
331 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
332
333 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
334 if( ret != 0 )
335 return( ret );
336
337 if( output_len - len_done > HASH_BLOCK_BYTES )
338 use_len = HASH_BLOCK_BYTES;
339 else
340 use_len = output_len - len_done;
341
342 memcpy( output + len_done, tmp, use_len );
343 len_done += use_len;
344 }
345
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200346 mbedtls_zeroize( tmp, sizeof( tmp ) );
347
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200348 return( 0 );
349}
350
351#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200352#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200353#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200354#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
355
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
357 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
358 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
359 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
360 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
361 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
362 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
363 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
364 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
365 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
366 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200367#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100368#endif
369
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200370#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200371#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100372#endif
373
374/*
375 * Curve types: internal for now, might be exposed later
376 */
377typedef enum
378{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200379 ECP_TYPE_NONE = 0,
380 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
381 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100382} ecp_curve_type;
383
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100384/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200385 * List of supported curves:
386 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200387 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200388 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200389 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100390 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100391 * Curves are listed in order: largest curves first, and for a given size,
392 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200393 *
394 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200395 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200397{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
399 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200400#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
402 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100403#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
405 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200406#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
408 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100409#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
411 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200412#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
414 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100415#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
417 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100418#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
420 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200421#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
423 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100424#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
426 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100427#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
429 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100430#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200432};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100433
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200434#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
435 sizeof( ecp_supported_curves[0] )
436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200438
439/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200440 * List of supported curves and associated info
441 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200443{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200444 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200445}
446
447/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100448 * List of supported curves, group ID only
449 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100451{
452 static int init_done = 0;
453
454 if( ! init_done )
455 {
456 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 for( curve_info = mbedtls_ecp_curve_list();
460 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100461 curve_info++ )
462 {
463 ecp_supported_grp_id[i++] = curve_info->grp_id;
464 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100466
467 init_done = 1;
468 }
469
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200470 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100471}
472
473/*
474 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476const 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 +0200477{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 for( curve_info = mbedtls_ecp_curve_list();
481 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200482 curve_info++ )
483 {
484 if( curve_info->grp_id == grp_id )
485 return( curve_info );
486 }
487
488 return( NULL );
489}
490
491/*
492 * Get the curve info from the TLS identifier
493 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200495{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 for( curve_info = mbedtls_ecp_curve_list();
499 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200500 curve_info++ )
501 {
502 if( curve_info->tls_id == tls_id )
503 return( curve_info );
504 }
505
506 return( NULL );
507}
508
509/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100510 * Get the curve info from the name
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100513{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 for( curve_info = mbedtls_ecp_curve_list();
517 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100518 curve_info++ )
519 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200520 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100521 return( curve_info );
522 }
523
524 return( NULL );
525}
526
527/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100528 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100529 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100531{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100532 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200533 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100534
535 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200536 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100537 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200538 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100539}
540
541/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100542 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100545{
546 if( pt == NULL )
547 return;
548
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 mbedtls_mpi_init( &pt->X );
550 mbedtls_mpi_init( &pt->Y );
551 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100552}
553
554/*
555 * Initialize (the components of) a group
556 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100558{
559 if( grp == NULL )
560 return;
561
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100563}
564
565/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200566 * Initialize (the components of) a key pair
567 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200569{
Paul Bakker66d5d072014-06-17 16:39:18 +0200570 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200571 return;
572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 mbedtls_ecp_group_init( &key->grp );
574 mbedtls_mpi_init( &key->d );
575 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200576}
577
578/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100579 * Unallocate (the components of) a point
580 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200581void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100582{
583 if( pt == NULL )
584 return;
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_mpi_free( &( pt->X ) );
587 mbedtls_mpi_free( &( pt->Y ) );
588 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100589}
590
591/*
592 * Unallocate (the components of) a group
593 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100595{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200596 size_t i;
597
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100598 if( grp == NULL )
599 return;
600
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100601 if( grp->h != 1 )
602 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 mbedtls_mpi_free( &grp->P );
604 mbedtls_mpi_free( &grp->A );
605 mbedtls_mpi_free( &grp->B );
606 mbedtls_ecp_point_free( &grp->G );
607 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100608 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200609
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200610 if( grp->T != NULL )
611 {
612 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 mbedtls_ecp_point_free( &grp->T[i] );
614 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200615 }
616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100618}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100619
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100620/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200621 * Unallocate (the components of) a key pair
622 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200623void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200624{
Paul Bakker66d5d072014-06-17 16:39:18 +0200625 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200626 return;
627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 mbedtls_ecp_group_free( &key->grp );
629 mbedtls_mpi_free( &key->d );
630 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200631}
632
633/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200634 * Copy the contents of a point
635 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200637{
638 int ret;
639
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
641 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
642 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200643
644cleanup:
645 return( ret );
646}
647
648/*
649 * Copy the contents of a group object
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200652{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200653 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200654}
655
656/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100657 * Set point to zero
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100660{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100661 int ret;
662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
664 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
665 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100666
667cleanup:
668 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100669}
670
671/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100672 * Tell if a point is zero
673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100675{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100677}
678
679/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700680 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200681 */
682int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
683 const mbedtls_ecp_point *Q )
684{
685 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
686 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
687 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
688 {
689 return( 0 );
690 }
691
692 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
693}
694
695/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100696 * Import a non-zero point from ASCII strings
697 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100699 const char *x, const char *y )
700{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100701 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
704 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
705 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100706
707cleanup:
708 return( ret );
709}
710
711/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100712 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100713 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100715 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100716 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100717{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200718 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100719 size_t plen;
720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
722 format != MBEDTLS_ECP_PF_COMPRESSED )
723 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100724
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100725 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100726 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100729 {
730 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100732
733 buf[0] = 0x00;
734 *olen = 1;
735
736 return( 0 );
737 }
738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100742 {
743 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100744
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100745 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100747
748 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
750 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100751 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100753 {
754 *olen = plen + 1;
755
756 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
760 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100761 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100762
763cleanup:
764 return( ret );
765}
766
767/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100768 * Import a point from unsigned binary data (SEC1 2.3.4)
769 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100771 const unsigned char *buf, size_t ilen )
772{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100773 int ret;
774 size_t plen;
775
Paul Bakker82788fb2014-10-20 13:59:19 +0200776 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200778
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100779 if( buf[0] == 0x00 )
780 {
781 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100783 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100785 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100788
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100789 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100791
792 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
796 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
797 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100798
799cleanup:
800 return( ret );
801}
802
803/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100804 * Import a point from a TLS ECPoint record (RFC 4492)
805 * struct {
806 * opaque point <1..2^8-1>;
807 * } ECPoint;
808 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100810 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100811{
812 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100813 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100814
815 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200816 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100817 */
818 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100820
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100821 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100822 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100824
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100825 /*
826 * Save buffer start for read_binary and update buf
827 */
828 buf_start = *buf;
829 *buf += data_len;
830
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200831 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100832}
833
834/*
835 * Export a point as a TLS ECPoint record (RFC 4492)
836 * struct {
837 * opaque point <1..2^8-1>;
838 * } ECPoint;
839 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100841 int format, size_t *olen,
842 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100843{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100844 int ret;
845
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100846 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100847 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100848 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100849 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100851
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100853 olen, buf + 1, blen - 1) ) != 0 )
854 return( ret );
855
856 /*
857 * write length to the first byte and update total length
858 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200859 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100860 ++*olen;
861
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200862 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100863}
864
865/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100866 * Set a group from an ECParameters record (RFC 4492)
867 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200868int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100869{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200870 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100872
873 /*
874 * We expect at least three bytes (see below)
875 */
876 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100878
879 /*
880 * First byte is curve_type; only named_curve is handled
881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200882 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
883 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100884
885 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100886 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100887 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200888 tls_id = *(*buf)++;
889 tls_id <<= 8;
890 tls_id |= *(*buf)++;
891
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
893 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200894
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200895 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100896}
897
898/*
899 * Write the ECParameters record corresponding to a group (RFC 4492)
900 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100902 unsigned char *buf, size_t blen )
903{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200905
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200906 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
907 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200908
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100909 /*
910 * We are going to write 3 bytes (see below)
911 */
912 *olen = 3;
913 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100915
916 /*
917 * First byte is curve_type, always named_curve
918 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100920
921 /*
922 * Next two bytes are the namedcurve value
923 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200924 buf[0] = curve_info->tls_id >> 8;
925 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100926
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200927 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100928}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100929
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200930/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
932 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200933 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934 * 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 +0200935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200936static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200937{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200938 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200939
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200940 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200942
943 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200945 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200946 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200948 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200951
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200952 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200953 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
954 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200957 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200959
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200960cleanup:
961 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200962}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200963
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100964/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100965 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100966 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100967 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 * 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 +0100969 * bring the result back to this range.
970 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100971 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100972 */
973
974/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975 * 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 +0100976 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100978#define INC_MUL_COUNT mul_count++;
979#else
980#define INC_MUL_COUNT
981#endif
982
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200983#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100984 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100985
986/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200988 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100989 */
990#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200991 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
992 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100993
994/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 * 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 +0200996 * We known P, N and the result are positive, so sub_abs is correct, and
997 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100998 */
999#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
1001 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001002
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001003#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001004/*
1005 * For curves in short Weierstrass form, we do all the internal operations in
1006 * Jacobian coordinates.
1007 *
1008 * For multiplication, we'll use a comb method with coutermeasueres against
1009 * SPA, hence timing attacks.
1010 */
1011
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001012/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001013 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001014 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001015 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001017{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001018 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001022 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001023
Janos Follathb0697532016-08-18 12:38:46 +01001024#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001025 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001026 {
Janos Follathc44ab972016-11-18 16:38:23 +00001027 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +01001028 }
Janos Follath372697b2016-10-28 16:53:11 +01001029#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001031
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001032 /*
1033 * X = X / Z^2 mod p
1034 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001035 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1036 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1037 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 +01001038
1039 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001040 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1043 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 +01001044
1045 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001046 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001047 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001049
1050cleanup:
1051
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001052 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001053
1054 return( ret );
1055}
1056
1057/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001058 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001059 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001060 * (See for example Cohen's "A Course in Computational Algebraic Number
1061 * Theory", Algorithm 10.3.4.)
1062 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001063 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001064 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001065 *
1066 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001067 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1069 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001070{
1071 int ret;
1072 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001073 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001074
1075 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001076 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001077
Janos Follathb0697532016-08-18 12:38:46 +01001078#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001079 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001080 {
Janos Follathc44ab972016-11-18 16:38:23 +00001081 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001082 }
1083#endif
1084
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001085 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001086 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001087
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001088 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001089
1090 /*
1091 * c[i] = Z_0 * ... * Z_i
1092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001093 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001094 for( i = 1; i < t_len; i++ )
1095 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001097 MOD_MUL( c[i] );
1098 }
1099
1100 /*
1101 * u = 1 / (Z_0 * ... * Z_n) mod P
1102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001104
1105 for( i = t_len - 1; ; i-- )
1106 {
1107 /*
1108 * Zi = 1 / Z_i mod p
1109 * u = 1 / (Z_0 * ... * Z_i) mod P
1110 */
1111 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001112 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001113 }
1114 else
1115 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1117 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001118 }
1119
1120 /*
1121 * proceed as in normalize()
1122 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001123 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1124 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1125 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1126 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 +01001127
1128 /*
1129 * Post-precessing: reclaim some memory by shrinking coordinates
1130 * - not storing Z (always 1)
1131 * - shrinking other coordinates, but still keeping the same number of
1132 * limbs as P, as otherwise it will too likely be regrown too fast.
1133 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001134 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1135 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1136 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001137
1138 if( i == 0 )
1139 break;
1140 }
1141
1142cleanup:
1143
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001145 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 mbedtls_mpi_free( &c[i] );
1147 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001148
1149 return( ret );
1150}
1151
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001152/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001153 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1154 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001156static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1157 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001158 unsigned char inv )
1159{
1160 int ret;
1161 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001165
1166 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001167 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1168 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1169 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001170
1171cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001173
1174 return( ret );
1175}
1176
1177/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001178 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001179 *
Peter Dettmance661b22015-02-07 14:43:51 +07001180 * 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 +01001181 *
Peter Dettmance661b22015-02-07 14:43:51 +07001182 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1183 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1184 *
1185 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1186 *
1187 * Cost: 1D := 3M + 4S (A == 0)
1188 * 4M + 4S (A == -3)
1189 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001190 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001191static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1192 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001193{
1194 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001195 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001198 dbl_count++;
1199#endif
1200
Janos Follathb0697532016-08-18 12:38:46 +01001201#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001202 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001203 {
Janos Follathc44ab972016-11-18 16:38:23 +00001204 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001205 }
Janos Follath372697b2016-10-28 16:53:11 +01001206#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001207
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001208 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 +01001209
1210 /* Special case for A = -3 */
1211 if( grp->A.p == NULL )
1212 {
Peter Dettmance661b22015-02-07 14:43:51 +07001213 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001214 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1216 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1217 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1218 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001219 }
1220 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001221 {
Peter Dettmance661b22015-02-07 14:43:51 +07001222 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001223 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1224 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001225
1226 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001227 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001228 {
1229 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1231 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1232 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1233 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001234 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001235 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001236
Peter Dettmance661b22015-02-07 14:43:51 +07001237 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001238 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1239 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1240 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1241 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001242
Peter Dettmance661b22015-02-07 14:43:51 +07001243 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001244 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1245 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001246
1247 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001248 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1249 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1250 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001251
1252 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001253 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1254 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1255 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001256
1257 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001258 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1259 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001260
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001261 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1262 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1263 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001264
1265cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001266 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 +02001267
1268 return( ret );
1269}
1270
1271/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001272 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001273 *
1274 * The coordinates of Q must be normalized (= affine),
1275 * but those of P don't need to. R is not normalized.
1276 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001277 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001278 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001279 * - at each step, P, Q and R are multiples of the base point, the factor
1280 * being less than its order, so none of them is zero;
1281 * - Q is an odd multiple of the base point, P an even multiple,
1282 * due to the choice of precomputed points in the modified comb method.
1283 * So branches for these cases do not leak secret information.
1284 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001285 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1286 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001287 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1290 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001291{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001292 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001296 add_count++;
1297#endif
1298
Janos Follathb0697532016-08-18 12:38:46 +01001299#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001300 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001301 {
Janos Follathc44ab972016-11-18 16:38:23 +00001302 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001303 }
Janos Follath372697b2016-10-28 16:53:11 +01001304#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001305
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001306 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001307 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001308 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1310 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1313 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001314
1315 /*
1316 * Make sure Q coordinates are normalized
1317 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001318 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1319 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001321 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1322 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1325 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1326 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1327 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1328 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001330
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001331 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001333 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001335 {
1336 ret = ecp_double_jac( grp, R, P );
1337 goto cleanup;
1338 }
1339 else
1340 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001342 goto cleanup;
1343 }
1344 }
1345
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1347 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1349 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1353 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1355 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1356 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1357 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001359 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1360 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1361 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001362
1363cleanup:
1364
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1366 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001367
1368 return( ret );
1369}
1370
1371/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001372 * Randomize jacobian coordinates:
1373 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001374 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001375 *
1376 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001377 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001378static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001379 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1380{
1381 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001383 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001384 int count = 0;
1385
Janos Follathb0697532016-08-18 12:38:46 +01001386#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001387 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001388 {
Janos Follathc44ab972016-11-18 16:38:23 +00001389 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001390 }
Janos Follath372697b2016-10-28 16:53:11 +01001391#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001392
1393 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001394 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001395
1396 /* Generate l such that 1 < l < p */
1397 do
1398 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001399 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001400
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1402 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001403
1404 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001405 {
1406 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1407 goto cleanup;
1408 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001409 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001411
1412 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413 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 +02001414
1415 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001416 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1417 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 +02001418
1419 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001420 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1421 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 +02001422
1423cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001425
1426 return( ret );
1427}
1428
1429/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001430 * Check and define parameters used by the comb method (see below for details)
1431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1433#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001434#endif
1435
1436/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001437#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001438
1439/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001441
1442/*
1443 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001444 *
1445 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001446 * modified version that provides resistance to SPA by avoiding zero
1447 * digits in the representation as in [3]. We modify the method further by
1448 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001449 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001450 *
1451 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1452 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1453 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001454 *
1455 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001456 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001457 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001458 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001459 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1460 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001461 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001462static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001463 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001464{
1465 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001466 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001467
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001468 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001469
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001470 /* First get the classical comb values (except for x_d = 0) */
1471 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001472 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001474
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001475 /* Now make sure x_1 .. x_d are odd */
1476 c = 0;
1477 for( i = 1; i <= d; i++ )
1478 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001479 /* Add carry and update it */
1480 cc = x[i] & c;
1481 x[i] = x[i] ^ c;
1482 c = cc;
1483
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001484 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001485 adjust = 1 - ( x[i] & 0x01 );
1486 c |= x[i] & ( x[i-1] * adjust );
1487 x[i] = x[i] ^ ( x[i-1] * adjust );
1488 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001489 }
1490}
1491
1492/*
1493 * Precompute points for the comb method
1494 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001495 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1496 * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001497 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001498 * T must be able to hold 2^{w - 1} elements
1499 *
1500 * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001502static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1503 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001504 unsigned char w, size_t d )
1505{
1506 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001507 unsigned char i, k;
1508 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001510
1511 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001512 * Set T[0] = P and
1513 * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001514 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001515 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001516
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001517 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001518 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001519 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001520 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001522 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001523 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001524
1525 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001526 }
1527
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001529
1530 /*
1531 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001532 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001533 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001534 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001535 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001536 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001537 j = i;
1538 while( j-- )
1539 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001540 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001541 TT[k++] = &T[i + j];
1542 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001543 }
1544
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001545 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001546
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001547cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001548
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001549 return( ret );
1550}
1551
1552/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001553 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001554 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1556 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001557 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001558{
1559 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001560 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001561
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001562 /* Ignore the "sign" bit and scale down */
1563 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001564
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001565 /* Read the whole table to thwart cache-based timing attacks */
1566 for( j = 0; j < t_len; j++ )
1567 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001570 }
1571
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001572 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001574
1575cleanup:
1576 return( ret );
1577}
1578
1579/*
1580 * Core multiplication algorithm for the (modified) comb method.
1581 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001582 *
1583 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001584 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1586 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001587 const unsigned char x[], size_t d,
1588 int (*f_rng)(void *, unsigned char *, size_t),
1589 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001590{
1591 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001593 size_t i;
1594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001596
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001597 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001598 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1600 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001601#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001602 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001603#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001605
1606 while( i-- != 0 )
1607 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001608 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1609 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1610 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001611 }
1612
1613cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001616
1617 return( ret );
1618}
1619
1620/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001621 * Multiplication using the comb method,
1622 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1625 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001626 int (*f_rng)(void *, unsigned char *, size_t),
1627 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001628{
1629 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001630 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1631 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001632 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001633 mbedtls_ecp_point *T;
1634 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001636 mbedtls_mpi_init( &M );
1637 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001638
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001639 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001640 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1641 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001642
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001643 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001644 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001645 * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001646 * (see costs of the various parts, with 1S = 1M)
1647 */
1648 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001649
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001650 /*
1651 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001652 * Just adding one avoids upping the cost of the first mul too much,
1653 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001654 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001655#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1656 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1657 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001658 if( p_eq_g )
1659 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001660#else
1661 p_eq_g = 0;
1662#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001663
1664 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001665 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001666 * (The last test is useful only for very small curves in the test suite.)
1667 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001668 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1669 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001670 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001671 w = 2;
1672
1673 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001674 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001675 d = ( grp->nbits + w - 1 ) / w;
1676
1677 /*
1678 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001679 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001680 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001681 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001682
1683 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001684 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001685 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001686 if( T == NULL )
1687 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001688 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001689 goto cleanup;
1690 }
1691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001693
1694 if( p_eq_g )
1695 {
1696 grp->T = T;
1697 grp->T_size = pre_len;
1698 }
1699 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001700
1701 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001702 * Make sure M is odd (M = m or M = N - m, since N is odd)
1703 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001704 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1707 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1708 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001709
1710 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001711 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001712 */
1713 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001714 MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001715
1716 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001717 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001720
1721 /*
1722 * Knowledge of the jacobian coordinates may leak the last few bits of the
1723 * scalar [1], and since our MPI implementation isn't constant-flow,
1724 * inversion (used for coordinate normalization) may leak the full value
1725 * of its input via side-channels [2].
1726 *
1727 * [1] https://eprint.iacr.org/2003/191
1728 * [2] https://eprint.iacr.org/2020/055
1729 *
1730 * Avoid the leak by randomizing coordinates before we normalize them.
1731 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001732#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001733 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001734#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001735 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001736 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001737
1738cleanup:
1739
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001740 /* There are two cases where T is not stored in grp:
1741 * - P != G
1742 * - An intermediate operation failed before setting grp->T
1743 * In either case, T must be freed.
1744 */
1745 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001746 {
1747 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001748 mbedtls_ecp_point_free( &T[i] );
1749 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001750 }
1751
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001752 mbedtls_mpi_free( &M );
1753 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001754
1755 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001757
1758 return( ret );
1759}
1760
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001761#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001762
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001763#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001764/*
1765 * For Montgomery curves, we do all the internal arithmetic in projective
1766 * coordinates. Import/export of points uses only the x coordinates, which is
1767 * internaly represented as X / Z.
1768 *
1769 * For scalar multiplication, we'll use a Montgomery ladder.
1770 */
1771
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001772/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001773 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1774 * Cost: 1M + 1I
1775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001777{
1778 int ret;
1779
Janos Follathb0697532016-08-18 12:38:46 +01001780#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001781 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001782 {
Janos Follathc44ab972016-11-18 16:38:23 +00001783 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001784 }
Janos Follath372697b2016-10-28 16:53:11 +01001785#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001786
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1788 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1789 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001790
1791cleanup:
1792 return( ret );
1793}
1794
1795/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001796 * Randomize projective x/z coordinates:
1797 * (X, Z) -> (l X, l Z) for random l
1798 * This is sort of the reverse operation of ecp_normalize_mxz().
1799 *
1800 * This countermeasure was first suggested in [2].
1801 * Cost: 2M
1802 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001803static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001804 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1805{
1806 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001807 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001808 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001809 int count = 0;
1810
Janos Follathb0697532016-08-18 12:38:46 +01001811#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001812 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001813 {
Janos Follathc44ab972016-11-18 16:38:23 +00001814 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001815 }
Janos Follath372697b2016-10-28 16:53:11 +01001816#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001817
1818 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001820
1821 /* Generate l such that 1 < l < p */
1822 do
1823 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001824 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001826 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1827 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001828
1829 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001830 {
1831 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1832 goto cleanup;
1833 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001834 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001836
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001837 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1838 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 +01001839
1840cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001842
1843 return( ret );
1844}
1845
1846/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001847 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1848 * for Montgomery curves in x/z coordinates.
1849 *
1850 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1851 * with
1852 * d = X1
1853 * P = (X2, Z2)
1854 * Q = (X3, Z3)
1855 * R = (X4, Z4)
1856 * S = (X5, Z5)
1857 * and eliminating temporary variables tO, ..., t4.
1858 *
1859 * Cost: 5M + 4S
1860 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001861static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1862 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1863 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1864 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001865{
1866 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001867 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001868
Janos Follathb0697532016-08-18 12:38:46 +01001869#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001870 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001871 {
Janos Follathc44ab972016-11-18 16:38:23 +00001872 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001873 }
Janos Follath372697b2016-10-28 16:53:11 +01001874#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001875
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001876 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1877 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1878 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001879
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1890 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1894 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1895 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1896 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1897 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 +01001898
1899cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1901 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1902 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001903
1904 return( ret );
1905}
1906
1907/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001908 * Multiplication with Montgomery ladder in x/z coordinates,
1909 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001910 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1912 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001913 int (*f_rng)(void *, unsigned char *, size_t),
1914 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001915{
1916 int ret;
1917 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001918 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 mbedtls_ecp_point RP;
1920 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001923
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001924 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1926 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001927
1928 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1931 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001932
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001933 /* RP.X might be sligtly larger than P, so reduce it */
1934 MOD_ADD( RP.X );
1935
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001936 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001937#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001938 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001939#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001940 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001941
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001942 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001943 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001944 while( i-- > 0 )
1945 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001947 /*
1948 * if (b) R = 2R + P else R = 2R,
1949 * which is:
1950 * if (b) double_add( RP, R, RP, R )
1951 * else double_add( R, RP, R, RP )
1952 * but using safe conditional swaps to avoid leaks
1953 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001954 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1956 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1957 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1958 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001959 }
1960
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001961 /*
1962 * Knowledge of the projective coordinates may leak the last few bits of the
1963 * scalar [1], and since our MPI implementation isn't constant-flow,
1964 * inversion (used for coordinate normalization) may leak the full value
1965 * of its input via side-channels [2].
1966 *
1967 * [1] https://eprint.iacr.org/2003/191
1968 * [2] https://eprint.iacr.org/2020/055
1969 *
1970 * Avoid the leak by randomizing coordinates before we normalize them.
1971 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001972#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001973 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001974#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001975 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001978
1979cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001980 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001981
1982 return( ret );
1983}
1984
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001985#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001986
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001987/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001988 * Multiplication R = m * P
1989 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1991 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001992 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1993{
Janos Follathb0697532016-08-18 12:38:46 +01001994 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001995#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1996 char is_grp_capable = 0;
1997#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001998#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1999 ecp_drbg_context drbg_ctx;
2000
2001 ecp_drbg_init( &drbg_ctx );
2002#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002003
2004 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002005 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
2006 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002007
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002008 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
2009 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002010 return( ret );
2011
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002012#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2013 if( f_rng == NULL )
2014 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002015 const size_t m_len = ( grp->nbits + 7 ) / 8;
2016 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002017 f_rng = &ecp_drbg_random;
2018 p_rng = &drbg_ctx;
2019 }
2020#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2021
Janos Follathc44ab972016-11-18 16:38:23 +00002022#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002023 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002024 {
Janos Follathc44ab972016-11-18 16:38:23 +00002025 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002026 }
Janos Follathc44ab972016-11-18 16:38:23 +00002027#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002028
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002029#if defined(ECP_MONTGOMERY)
2030 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002031 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002032#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002033#if defined(ECP_SHORTWEIERSTRASS)
2034 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002035 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002036#endif
Janos Follathb0697532016-08-18 12:38:46 +01002037
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002038#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2039cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002040#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002041#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002042 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002043 {
Janos Follathc44ab972016-11-18 16:38:23 +00002044 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002045 }
Janos Follathc44ab972016-11-18 16:38:23 +00002046#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002047
2048#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2049 ecp_drbg_free( &drbg_ctx );
2050#endif
2051
Janos Follathb0697532016-08-18 12:38:46 +01002052 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002053}
2054
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002055#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002056/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002057 * Check that an affine point is valid as a public key,
2058 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002061{
2062 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002064
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002065 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2067 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2068 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2069 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2070 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002073
2074 /*
2075 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002076 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002077 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002078 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2079 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002080
2081 /* Special case for A = -3 */
2082 if( grp->A.p == NULL )
2083 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002084 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002085 }
2086 else
2087 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002089 }
2090
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002091 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2092 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002093
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002094 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2095 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002096
2097cleanup:
2098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002099 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002100
2101 return( ret );
2102}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002103#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002104
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002105/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002106 * R = m * P with shortcuts for m == 1 and m == -1
2107 * NOT constant-time - ONLY for short Weierstrass!
2108 */
2109static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2110 mbedtls_ecp_point *R,
2111 const mbedtls_mpi *m,
2112 const mbedtls_ecp_point *P )
2113{
2114 int ret;
2115
2116 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2117 {
2118 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2119 }
2120 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2121 {
2122 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2123 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2124 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2125 }
2126 else
2127 {
2128 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2129 }
2130
2131cleanup:
2132 return( ret );
2133}
2134
2135/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002136 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002137 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002138 */
2139int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2140 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2141 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2142{
2143 int ret;
2144 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002145#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2146 char is_grp_capable = 0;
2147#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002148
2149 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2150 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2151
2152 mbedtls_ecp_point_init( &mP );
2153
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002154 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2155 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002156
Janos Follathc44ab972016-11-18 16:38:23 +00002157#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002158 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002159 {
Janos Follathc44ab972016-11-18 16:38:23 +00002160 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002161 }
Janos Follath430d3372016-11-03 14:25:37 +00002162
Janos Follathc44ab972016-11-18 16:38:23 +00002163#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002164 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2165 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2166
2167cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002168
Janos Follathc44ab972016-11-18 16:38:23 +00002169#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2170 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002171 {
Janos Follathc44ab972016-11-18 16:38:23 +00002172 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002173 }
Janos Follathb0697532016-08-18 12:38:46 +01002174
Janos Follathc44ab972016-11-18 16:38:23 +00002175#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002176 mbedtls_ecp_point_free( &mP );
2177
2178 return( ret );
2179}
2180
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002181
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002182#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002183/*
2184 * Check validity of a public key for Montgomery curves with x-only schemes
2185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002187{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002188 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002189 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2190 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002191
2192 return( 0 );
2193}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002194#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002195
2196/*
2197 * Check that a point is valid as a public key
2198 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002200{
2201 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2203 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002204
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002205#if defined(ECP_MONTGOMERY)
2206 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002207 return( ecp_check_pubkey_mx( grp, pt ) );
2208#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002209#if defined(ECP_SHORTWEIERSTRASS)
2210 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002211 return( ecp_check_pubkey_sw( grp, pt ) );
2212#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002213 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002214}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002215
2216/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002218 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002220{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002221#if defined(ECP_MONTGOMERY)
2222 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002223 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002224 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2226 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2227 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002228 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002229 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002230 else
2231 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002232 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002233#endif /* ECP_MONTGOMERY */
2234#if defined(ECP_SHORTWEIERSTRASS)
2235 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002236 {
2237 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002238 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2239 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2240 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002241 else
2242 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002243 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002244#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002245
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002247}
2248
2249/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002250 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002251 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002252int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2253 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002254 int (*f_rng)(void *, unsigned char *, size_t),
2255 void *p_rng )
2256{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002257 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002258 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002259
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002260#if defined(ECP_MONTGOMERY)
2261 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002262 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002263 /* [M225] page 5 */
2264 size_t b;
2265
Janos Follath98e28a72016-05-31 14:03:54 +01002266 do {
2267 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2268 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002269
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002270 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002271 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002272 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002274 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002275 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002276
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002277 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002278 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2279 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2280 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002281 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002282#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002283
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002284#if defined(ECP_SHORTWEIERSTRASS)
2285 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002286 {
2287 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002288 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002289 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002290
2291 /*
2292 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2293 * - use the same byte ordering;
2294 * - keep the leftmost nbits bits of the generated octet string;
2295 * - try until result is in the desired range.
2296 * This also avoids any biais, which is especially important for ECDSA.
2297 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002298 do
2299 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002300 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002302
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002303 /*
2304 * Each try has at worst a probability 1/2 of failing (the msb has
2305 * a probability 1/2 of being 0, and then the result will be < N),
2306 * so after 30 tries failure probability is a most 2**(-30).
2307 *
2308 * For most curves, 1 try is enough with overwhelming probability,
2309 * since N starts with a lot of 1s in binary, but some curves
2310 * such as secp224k1 are actually very close to the worst case.
2311 */
2312 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002314
Janos Follathc3b376e2019-10-11 14:21:53 +01002315 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002316 if( ret != 0 )
2317 {
2318 goto cleanup;
2319 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002320 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002321 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002322 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002323#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002324
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002325cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002326 return( ret );
2327}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002328
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002329/*
2330 * Generate a keypair with configurable base point
2331 */
2332int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2333 const mbedtls_ecp_point *G,
2334 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2335 int (*f_rng)(void *, unsigned char *, size_t),
2336 void *p_rng )
2337{
2338 int ret;
2339
2340 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2341 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2342
2343cleanup:
2344 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002345}
2346
2347/*
2348 * Generate key pair, wrapper for conventional base point
2349 */
2350int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2351 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2352 int (*f_rng)(void *, unsigned char *, size_t),
2353 void *p_rng )
2354{
2355 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002356}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002357
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002358/*
2359 * Generate a keypair, prettier wrapper
2360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002362 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2363{
2364 int ret;
2365
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002366 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002367 return( ret );
2368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002370}
2371
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002372/*
2373 * Check a public-private key pair
2374 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002376{
2377 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002378 mbedtls_ecp_point Q;
2379 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002382 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2384 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2385 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002386 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002388 }
2389
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_ecp_point_init( &Q );
2391 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393 /* mbedtls_ecp_mul() needs a non-const group... */
2394 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002395
2396 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002399 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2400 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2401 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002403 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002404 goto cleanup;
2405 }
2406
2407cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002408 mbedtls_ecp_point_free( &Q );
2409 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002410
2411 return( ret );
2412}
2413
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002414#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002415
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002416#if defined(ECP_ONE_STEP_KDF)
2417/*
2418 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2419 * but unofficial ones can be found at:
2420 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2421 *
2422 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002423 * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +02002424 * less than one block).
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002425 */
2426#if defined(MBEDTLS_SHA512_C)
2427
2428static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002429 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
2430 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002431};
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002432static const uint8_t test_kdf_out[40] = {
2433 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
2434 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
2435 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
2436 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
2437 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002438};
2439
2440#elif defined(MBEDTLS_SHA256_C)
2441
2442static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002443 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
2444 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002445};
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002446static const uint8_t test_kdf_out[40] = {
2447 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
2448 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
2449 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
2450 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
2451 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002452};
2453
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002454#endif
2455
2456static int ecp_kdf_self_test( void )
2457{
2458 int ret;
2459 ecp_drbg_context kdf_ctx;
2460 mbedtls_mpi scalar;
2461 uint8_t out[sizeof( test_kdf_out )];
2462
2463 ecp_drbg_init( &kdf_ctx );
2464 mbedtls_mpi_init( &scalar );
2465 memset( out, 0, sizeof( out ) );
2466
2467 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2468 test_kdf_z, sizeof( test_kdf_z ) ) );
2469
2470 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2471 &scalar, sizeof( test_kdf_z ) ) );
2472
2473 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2474
2475 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2476 ret = -1;
2477
2478cleanup:
2479 ecp_drbg_free( &kdf_ctx );
2480 mbedtls_mpi_free( &scalar );
2481
2482 return( ret );
2483}
2484#endif /* ECP_ONE_STEP_KDF */
2485
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002486/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002487 * Checkup routine
2488 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002490{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002491 int ret;
2492 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002493 mbedtls_ecp_group grp;
2494 mbedtls_ecp_point R, P;
2495 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002496 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002497 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002498 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002499 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002500 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002501 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002502 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002503 "400000000000000000000000000000000000000000000000", /* one and zeros */
2504 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2505 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002506 };
2507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 mbedtls_ecp_group_init( &grp );
2509 mbedtls_ecp_point_init( &R );
2510 mbedtls_ecp_point_init( &P );
2511 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002512
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002513 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002515 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002516#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002517 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002518#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002519
2520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002522
2523 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2525 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002526
2527 add_count = 0;
2528 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002529 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002530 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2531 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002532
2533 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2534 {
2535 add_c_prev = add_count;
2536 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002537 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002538 add_count = 0;
2539 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002540 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2543 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002544
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002545 if( add_count != add_c_prev ||
2546 dbl_count != dbl_c_prev ||
2547 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002548 {
2549 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002551
2552 ret = 1;
2553 goto cleanup;
2554 }
2555 }
2556
2557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002559
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002560 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002562 /* We computed P = 2G last time, use it */
2563
2564 add_count = 0;
2565 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002566 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002567 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2568 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002569
2570 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2571 {
2572 add_c_prev = add_count;
2573 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002574 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002575 add_count = 0;
2576 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002577 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2580 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002581
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002582 if( add_count != add_c_prev ||
2583 dbl_count != dbl_c_prev ||
2584 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002585 {
2586 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002587 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002588
2589 ret = 1;
2590 goto cleanup;
2591 }
2592 }
2593
2594 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002595 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002596
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002597#if defined(ECP_ONE_STEP_KDF)
2598 if( verbose != 0 )
2599 mbedtls_printf( " ECP test #3 (internal KDF): " );
2600
2601 ret = ecp_kdf_self_test();
2602 if( ret != 0 )
2603 {
2604 if( verbose != 0 )
2605 mbedtls_printf( "failed\n" );
2606
2607 ret = 1;
2608 goto cleanup;
2609 }
2610
2611 if( verbose != 0 )
2612 mbedtls_printf( "passed\n" );
2613#endif /* ECP_ONE_STEP_KDF */
2614
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002615cleanup:
2616
2617 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002619
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002620 mbedtls_ecp_group_free( &grp );
2621 mbedtls_ecp_point_free( &R );
2622 mbedtls_ecp_point_free( &P );
2623 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002624
2625 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002627
2628 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002629}
2630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002631#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002632
Janos Follathb0697532016-08-18 12:38:46 +01002633#endif /* !MBEDTLS_ECP_ALT */
2634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002635#endif /* MBEDTLS_ECP_C */