blob: 897c01e1432e8e4f397d7f54d075bb7a610315a6 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
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 * **********
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010045 */
46
47/*
48 * References:
49 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010050 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010051 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010052 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010053 * RFC 4492 for the related TLS structures and constants
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020054 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020055 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010056 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020057 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020058 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
59 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
60 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010061 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020062 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010063 * render ECC resistant against Side Channel Attacks. IACR Cryptology
64 * ePrint Archive, 2004, vol. 2004, p. 342.
65 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010066 */
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000069#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020070#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020072#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010073
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010075
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000076#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000077#include "mbedtls/threading.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020078
Rich Evans00ab4702015-02-06 13:43:58 +000079#include <string.h>
80
Janos Follathb0697532016-08-18 12:38:46 +010081#if !defined(MBEDTLS_ECP_ALT)
82
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000084#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020085#else
Rich Evans00ab4702015-02-06 13:43:58 +000086#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000087#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020088#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020089#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020091#endif
92
Janos Follath47d28f02016-11-01 13:22:05 +000093#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +010094
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020095#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020096#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020097#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020098#elif defined(MBEDTLS_CTR_DRBG_C)
99#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200100#elif defined(MBEDTLS_SHA512_C)
101#include "mbedtls/sha512.h"
102#elif defined(MBEDTLS_SHA256_C)
103#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200104#else
105#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
106#endif
107#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
108
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +0100109#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
110 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +0100111#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +0200112#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +0100113
Paul Bakker34617722014-06-13 17:20:13 +0200114/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +0200116 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
117}
118
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100120/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100121 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200122 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100123 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100124static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100125#endif
126
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200127#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
128/*
129 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200130 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200131 * that people will pass non-NULL RNG when they care about side-channels, but
132 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
133 * no opportunity for the user to do anything about it.
134 *
135 * The obvious strategies for addressing that include:
136 * - change those APIs so that they take RNG arguments;
137 * - require a global RNG to be available to all crypto modules.
138 *
139 * Unfortunately those would break compatibility. So what we do instead is
140 * have our own internal DRBG instance, seeded from the secret scalar.
141 *
142 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200143 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200144 */
145
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200146#if defined(MBEDTLS_HMAC_DRBG_C)
147
148/* DRBG context type */
149typedef mbedtls_hmac_drbg_context ecp_drbg_context;
150
151/* DRBG context init */
152static inline void ecp_drbg_init( ecp_drbg_context *ctx )
153{
154 mbedtls_hmac_drbg_init( ctx );
155}
156
157/* DRBG context free */
158static inline void ecp_drbg_free( ecp_drbg_context *ctx )
159{
160 mbedtls_hmac_drbg_free( ctx );
161}
162
163/* DRBG function */
164static inline int ecp_drbg_random( void *p_rng,
165 unsigned char *output, size_t output_len )
166{
167 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
168}
169
170/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200171static int ecp_drbg_seed( ecp_drbg_context *ctx,
172 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200173{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200174 int ret;
175 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200176 /* The list starts with strong hashes */
177 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
178 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
179
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200180 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
181 secret_bytes, secret_len ) );
182
183 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
184
185cleanup:
186 mbedtls_zeroize( secret_bytes, secret_len );
187
188 return( ret );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200189}
190
191#elif defined(MBEDTLS_CTR_DRBG_C)
192
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200193/* DRBG context type */
194typedef mbedtls_ctr_drbg_context ecp_drbg_context;
195
196/* DRBG context init */
197static inline void ecp_drbg_init( ecp_drbg_context *ctx )
198{
199 mbedtls_ctr_drbg_init( ctx );
200}
201
202/* DRBG context free */
203static inline void ecp_drbg_free( ecp_drbg_context *ctx )
204{
205 mbedtls_ctr_drbg_free( ctx );
206}
207
208/* DRBG function */
209static inline int ecp_drbg_random( void *p_rng,
210 unsigned char *output, size_t output_len )
211{
212 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
213}
214
215/*
216 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
217 * we need to pass an entropy function when seeding. So we use a dummy
218 * function for that, and pass the actual entropy as customisation string.
219 * (During seeding of CTR_DRBG the entropy input and customisation string are
220 * concatenated before being used to update the secret state.)
221 */
222static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
223{
224 (void) ctx;
225 memset( out, 0, len );
226 return( 0 );
227}
228
229/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200230static int ecp_drbg_seed( ecp_drbg_context *ctx,
231 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200232{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200233 int ret;
234 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200235
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
237 secret_bytes, secret_len ) );
238
239 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
240 secret_bytes, secret_len );
241
242cleanup:
243 mbedtls_zeroize( secret_bytes, secret_len );
244
245 return( ret );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200246}
247
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200248#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200249
250/* This will be used in the self-test function */
251#define ECP_ONE_STEP_KDF
252
253/*
254 * We need to expand secret data (the scalar) into a longer stream of bytes.
255 *
256 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
257 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
258 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
259 *
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200260 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200261 */
262#if defined(MBEDTLS_SHA512_C)
263
264#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
265#define HASH_BLOCK_BYTES ( 512 / 8 )
266
267#elif defined(MBEDTLS_SHA256_C)
268
269#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
270#define HASH_BLOCK_BYTES ( 256 / 8 )
271
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200272#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200273
274/*
275 * State consists of a 32-bit counter plus the secret value.
276 *
277 * We stored them concatenated in a single buffer as that's what will get
278 * passed to the hash function.
279 */
280typedef struct {
281 size_t total_len;
282 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
283} ecp_drbg_context;
284
285static void ecp_drbg_init( ecp_drbg_context *ctx )
286{
287 memset( ctx, 0, sizeof( ecp_drbg_context ) );
288}
289
290static void ecp_drbg_free( ecp_drbg_context *ctx )
291{
292 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
293}
294
295static int ecp_drbg_seed( ecp_drbg_context *ctx,
296 const mbedtls_mpi *secret, size_t secret_len )
297{
298 ctx->total_len = 4 + secret_len;
299 memset( ctx->buf, 0, 4);
300 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
301}
302
303static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
304{
305 ecp_drbg_context *ctx = p_rng;
306 int ret;
307 size_t len_done = 0;
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200308 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200309
310 while( len_done < output_len )
311 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200312 uint8_t use_len;
313
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200314 /* This function is only called for coordinate randomisation, which
315 * happens only twice in a scalar multiplication. Each time needs a
316 * random value in the range [2, p-1], and gets it by drawing len(p)
317 * bytes from this function, and retrying up to 10 times if unlucky.
318 *
319 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200320 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
321 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200322 *
323 * Since we don't need to draw more that 255 blocks, don't bother
324 * with carry propagation and just return an error instead. We can
325 * change that it we even need to draw more blinding values.
326 */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200327 ctx->buf[3] += 1;
328 if( ctx->buf[3] == 0 )
329 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
330
331 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
332 if( ret != 0 )
333 return( ret );
334
335 if( output_len - len_done > HASH_BLOCK_BYTES )
336 use_len = HASH_BLOCK_BYTES;
337 else
338 use_len = output_len - len_done;
339
340 memcpy( output + len_done, tmp, use_len );
341 len_done += use_len;
342 }
343
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200344 mbedtls_zeroize( tmp, sizeof( tmp ) );
345
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200346 return( 0 );
347}
348
349#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200350#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200351#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200352#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
355 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
356 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
357 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
358 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
359 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
360 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
361 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
362 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
363 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
364 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200365#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100366#endif
367
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200368#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200369#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100370#endif
371
372/*
373 * Curve types: internal for now, might be exposed later
374 */
375typedef enum
376{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200377 ECP_TYPE_NONE = 0,
378 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
379 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100380} ecp_curve_type;
381
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100382/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200383 * List of supported curves:
384 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200385 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200386 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200387 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100388 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100389 * Curves are listed in order: largest curves first, and for a given size,
390 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200391 *
392 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200395{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
397 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200398#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
400 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100401#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
403 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200404#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
406 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100407#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
409 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200410#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
412 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100413#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
415 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100416#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
418 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200419#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200420#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
421 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100422#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
424 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100425#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
427 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100428#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200430};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100431
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200432#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
433 sizeof( ecp_supported_curves[0] )
434
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200436
437/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200438 * List of supported curves and associated info
439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200441{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200442 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200443}
444
445/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100446 * List of supported curves, group ID only
447 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100449{
450 static int init_done = 0;
451
452 if( ! init_done )
453 {
454 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 for( curve_info = mbedtls_ecp_curve_list();
458 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100459 curve_info++ )
460 {
461 ecp_supported_grp_id[i++] = curve_info->grp_id;
462 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100464
465 init_done = 1;
466 }
467
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200468 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100469}
470
471/*
472 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474const 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 +0200475{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200477
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 for( curve_info = mbedtls_ecp_curve_list();
479 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200480 curve_info++ )
481 {
482 if( curve_info->grp_id == grp_id )
483 return( curve_info );
484 }
485
486 return( NULL );
487}
488
489/*
490 * Get the curve info from the TLS identifier
491 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200493{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 for( curve_info = mbedtls_ecp_curve_list();
497 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200498 curve_info++ )
499 {
500 if( curve_info->tls_id == tls_id )
501 return( curve_info );
502 }
503
504 return( NULL );
505}
506
507/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100508 * Get the curve info from the name
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100511{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 for( curve_info = mbedtls_ecp_curve_list();
515 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100516 curve_info++ )
517 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200518 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100519 return( curve_info );
520 }
521
522 return( NULL );
523}
524
525/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100526 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100529{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100530 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200531 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100532
533 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200534 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100535 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200536 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100537}
538
539/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100540 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100541 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100543{
544 if( pt == NULL )
545 return;
546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200547 mbedtls_mpi_init( &pt->X );
548 mbedtls_mpi_init( &pt->Y );
549 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100550}
551
552/*
553 * Initialize (the components of) a group
554 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100556{
557 if( grp == NULL )
558 return;
559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100561}
562
563/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200564 * Initialize (the components of) a key pair
565 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200567{
Paul Bakker66d5d072014-06-17 16:39:18 +0200568 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200569 return;
570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 mbedtls_ecp_group_init( &key->grp );
572 mbedtls_mpi_init( &key->d );
573 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200574}
575
576/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100577 * Unallocate (the components of) a point
578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100580{
581 if( pt == NULL )
582 return;
583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200584 mbedtls_mpi_free( &( pt->X ) );
585 mbedtls_mpi_free( &( pt->Y ) );
586 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100587}
588
589/*
590 * Unallocate (the components of) a group
591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100593{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200594 size_t i;
595
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100596 if( grp == NULL )
597 return;
598
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100599 if( grp->h != 1 )
600 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 mbedtls_mpi_free( &grp->P );
602 mbedtls_mpi_free( &grp->A );
603 mbedtls_mpi_free( &grp->B );
604 mbedtls_ecp_point_free( &grp->G );
605 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100606 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200607
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200608 if( grp->T != NULL )
609 {
610 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 mbedtls_ecp_point_free( &grp->T[i] );
612 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200613 }
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100616}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100617
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100618/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200619 * Unallocate (the components of) a key pair
620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200622{
Paul Bakker66d5d072014-06-17 16:39:18 +0200623 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200624 return;
625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_ecp_group_free( &key->grp );
627 mbedtls_mpi_free( &key->d );
628 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200629}
630
631/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200632 * Copy the contents of a point
633 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200635{
636 int ret;
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
639 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
640 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200641
642cleanup:
643 return( ret );
644}
645
646/*
647 * Copy the contents of a group object
648 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200650{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200651 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200652}
653
654/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100655 * Set point to zero
656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100658{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100659 int ret;
660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
662 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
663 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100664
665cleanup:
666 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100667}
668
669/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100670 * Tell if a point is zero
671 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100673{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100675}
676
677/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700678 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200679 */
680int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
681 const mbedtls_ecp_point *Q )
682{
683 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
684 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
685 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
686 {
687 return( 0 );
688 }
689
690 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
691}
692
693/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100694 * Import a non-zero point from ASCII strings
695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100697 const char *x, const char *y )
698{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100699 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
702 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
703 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100704
705cleanup:
706 return( ret );
707}
708
709/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100710 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100711 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100713 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100714 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100715{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200716 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100717 size_t plen;
718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
720 format != MBEDTLS_ECP_PF_COMPRESSED )
721 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100722
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100723 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100724 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100725 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100727 {
728 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100730
731 buf[0] = 0x00;
732 *olen = 1;
733
734 return( 0 );
735 }
736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100740 {
741 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100742
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100743 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200744 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100745
746 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
748 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100749 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100751 {
752 *olen = plen + 1;
753
754 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
758 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100759 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100760
761cleanup:
762 return( ret );
763}
764
765/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100766 * Import a point from unsigned binary data (SEC1 2.3.4)
767 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100769 const unsigned char *buf, size_t ilen )
770{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100771 int ret;
772 size_t plen;
773
Paul Bakker82788fb2014-10-20 13:59:19 +0200774 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200776
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100777 if( buf[0] == 0x00 )
778 {
779 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100781 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100783 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100786
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100787 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100789
790 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100792
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200793 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
794 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
795 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100796
797cleanup:
798 return( ret );
799}
800
801/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100802 * Import a point from a TLS ECPoint record (RFC 4492)
803 * struct {
804 * opaque point <1..2^8-1>;
805 * } ECPoint;
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100808 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100809{
810 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100811 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100812
813 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200814 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100815 */
816 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200817 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100818
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100819 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100820 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100822
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100823 /*
824 * Save buffer start for read_binary and update buf
825 */
826 buf_start = *buf;
827 *buf += data_len;
828
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100830}
831
832/*
833 * Export a point as a TLS ECPoint record (RFC 4492)
834 * struct {
835 * opaque point <1..2^8-1>;
836 * } ECPoint;
837 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100839 int format, size_t *olen,
840 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100841{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100842 int ret;
843
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100844 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100845 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100846 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100847 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100849
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100851 olen, buf + 1, blen - 1) ) != 0 )
852 return( ret );
853
854 /*
855 * write length to the first byte and update total length
856 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200857 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100858 ++*olen;
859
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200860 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100861}
862
863/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100864 * Set a group from an ECParameters record (RFC 4492)
865 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866int 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 +0100867{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200868 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100870
871 /*
872 * We expect at least three bytes (see below)
873 */
874 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100876
877 /*
878 * First byte is curve_type; only named_curve is handled
879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200880 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
881 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100882
883 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100884 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100885 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200886 tls_id = *(*buf)++;
887 tls_id <<= 8;
888 tls_id |= *(*buf)++;
889
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
891 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200892
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200893 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100894}
895
896/*
897 * Write the ECParameters record corresponding to a group (RFC 4492)
898 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100900 unsigned char *buf, size_t blen )
901{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
905 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200906
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100907 /*
908 * We are going to write 3 bytes (see below)
909 */
910 *olen = 3;
911 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100913
914 /*
915 * First byte is curve_type, always named_curve
916 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100918
919 /*
920 * Next two bytes are the namedcurve value
921 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200922 buf[0] = curve_info->tls_id >> 8;
923 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100924
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200925 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100926}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100927
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200928/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
930 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200931 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 * 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 +0200933 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200934static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200935{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200936 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200937
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200938 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200940
941 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200942 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200943 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200944 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200945 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200946 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200949
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200950 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
952 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200955 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200957
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200958cleanup:
959 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200960}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200961
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100962/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100963 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100964 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100965 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 * 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 +0100967 * bring the result back to this range.
968 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100969 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100970 */
971
972/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 * 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 +0100974 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200975#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100976#define INC_MUL_COUNT mul_count++;
977#else
978#define INC_MUL_COUNT
979#endif
980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200981#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100982 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100983
984/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200986 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100987 */
988#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
990 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100991
992/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200993 * 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 +0200994 * We known P, N and the result are positive, so sub_abs is correct, and
995 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100996 */
997#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
999 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001000
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001001#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001002/*
1003 * For curves in short Weierstrass form, we do all the internal operations in
1004 * Jacobian coordinates.
1005 *
1006 * For multiplication, we'll use a comb method with coutermeasueres against
1007 * SPA, hence timing attacks.
1008 */
1009
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001010/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001011 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001012 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001013 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001014static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001015{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001016 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001018
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001020 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001021
Janos Follathb0697532016-08-18 12:38:46 +01001022#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001023 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001024 {
Janos Follathc44ab972016-11-18 16:38:23 +00001025 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +01001026 }
Janos Follath372697b2016-10-28 16:53:11 +01001027#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001028 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001029
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001030 /*
1031 * X = X / Z^2 mod p
1032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001033 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1034 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1035 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 +01001036
1037 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001038 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001039 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1041 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 +01001042
1043 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001044 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001045 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001047
1048cleanup:
1049
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001051
1052 return( ret );
1053}
1054
1055/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001056 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001057 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001058 * (See for example Cohen's "A Course in Computational Algebraic Number
1059 * Theory", Algorithm 10.3.4.)
1060 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001061 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001062 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001063 *
1064 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1067 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001068{
1069 int ret;
1070 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001071 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001072
1073 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001074 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001075
Janos Follathb0697532016-08-18 12:38:46 +01001076#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001077 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001078 {
Janos Follathc44ab972016-11-18 16:38:23 +00001079 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001080 }
1081#endif
1082
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001083 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001084 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001086 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001087
1088 /*
1089 * c[i] = Z_0 * ... * Z_i
1090 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001091 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001092 for( i = 1; i < t_len; i++ )
1093 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001095 MOD_MUL( c[i] );
1096 }
1097
1098 /*
1099 * u = 1 / (Z_0 * ... * Z_n) mod P
1100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001101 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001102
1103 for( i = t_len - 1; ; i-- )
1104 {
1105 /*
1106 * Zi = 1 / Z_i mod p
1107 * u = 1 / (Z_0 * ... * Z_i) mod P
1108 */
1109 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001110 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001111 }
1112 else
1113 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1115 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001116 }
1117
1118 /*
1119 * proceed as in normalize()
1120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001121 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1122 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1123 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1124 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 +01001125
1126 /*
1127 * Post-precessing: reclaim some memory by shrinking coordinates
1128 * - not storing Z (always 1)
1129 * - shrinking other coordinates, but still keeping the same number of
1130 * limbs as P, as otherwise it will too likely be regrown too fast.
1131 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001132 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1133 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1134 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001135
1136 if( i == 0 )
1137 break;
1138 }
1139
1140cleanup:
1141
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001142 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001143 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 mbedtls_mpi_free( &c[i] );
1145 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001146
1147 return( ret );
1148}
1149
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001150/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001151 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1152 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1153 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001154static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1155 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001156 unsigned char inv )
1157{
1158 int ret;
1159 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001161
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001163
1164 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001165 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1166 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1167 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001168
1169cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001171
1172 return( ret );
1173}
1174
1175/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001176 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001177 *
Peter Dettmance661b22015-02-07 14:43:51 +07001178 * 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 +01001179 *
Peter Dettmance661b22015-02-07 14:43:51 +07001180 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1181 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1182 *
1183 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1184 *
1185 * Cost: 1D := 3M + 4S (A == 0)
1186 * 4M + 4S (A == -3)
1187 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001188 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001189static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1190 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001191{
1192 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001193 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001194
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001195#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001196 dbl_count++;
1197#endif
1198
Janos Follathb0697532016-08-18 12:38:46 +01001199#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001200 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001201 {
Janos Follathc44ab972016-11-18 16:38:23 +00001202 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001203 }
Janos Follath372697b2016-10-28 16:53:11 +01001204#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001205
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001206 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 +01001207
1208 /* Special case for A = -3 */
1209 if( grp->A.p == NULL )
1210 {
Peter Dettmance661b22015-02-07 14:43:51 +07001211 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001212 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1213 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1216 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001217 }
1218 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001219 {
Peter Dettmance661b22015-02-07 14:43:51 +07001220 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001221 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001223
1224 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001225 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001226 {
1227 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001228 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1229 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1230 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1231 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001232 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001233 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001234
Peter Dettmance661b22015-02-07 14:43:51 +07001235 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001236 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1237 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1238 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1239 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001240
Peter Dettmance661b22015-02-07 14:43:51 +07001241 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001242 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1243 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001244
1245 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001246 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1247 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1248 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001249
1250 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001251 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1252 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1253 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001254
1255 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001256 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1257 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001258
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001259 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1260 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1261 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001262
1263cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001264 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 +02001265
1266 return( ret );
1267}
1268
1269/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001270 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001271 *
1272 * The coordinates of Q must be normalized (= affine),
1273 * but those of P don't need to. R is not normalized.
1274 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001275 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001276 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001277 * - at each step, P, Q and R are multiples of the base point, the factor
1278 * being less than its order, so none of them is zero;
1279 * - Q is an odd multiple of the base point, P an even multiple,
1280 * due to the choice of precomputed points in the modified comb method.
1281 * So branches for these cases do not leak secret information.
1282 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001283 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1284 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001285 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001286 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1288 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001289{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001290 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001294 add_count++;
1295#endif
1296
Janos Follathb0697532016-08-18 12:38:46 +01001297#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001298 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001299 {
Janos Follathc44ab972016-11-18 16:38:23 +00001300 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001301 }
Janos Follath372697b2016-10-28 16:53:11 +01001302#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001303
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001304 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001305 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001306 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1308 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1311 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001312
1313 /*
1314 * Make sure Q coordinates are normalized
1315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1317 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1320 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001322 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1325 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001328
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001329 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001331 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001333 {
1334 ret = ecp_double_jac( grp, R, P );
1335 goto cleanup;
1336 }
1337 else
1338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001339 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001340 goto cleanup;
1341 }
1342 }
1343
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001344 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1345 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1346 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1347 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1348 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1349 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1350 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1351 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1352 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1353 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1355 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001357 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1358 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1359 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001360
1361cleanup:
1362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1364 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001365
1366 return( ret );
1367}
1368
1369/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001370 * Randomize jacobian coordinates:
1371 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001372 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001373 *
1374 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001377 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1378{
1379 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001380 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001381 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001382 int count = 0;
1383
Janos Follathb0697532016-08-18 12:38:46 +01001384#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001385 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001386 {
Janos Follathc44ab972016-11-18 16:38:23 +00001387 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001388 }
Janos Follath372697b2016-10-28 16:53:11 +01001389#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001390
1391 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001393
1394 /* Generate l such that 1 < l < p */
1395 do
1396 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001397 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001398
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001399 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1400 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001401
1402 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001403 {
1404 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1405 goto cleanup;
1406 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001407 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001409
1410 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411 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 +02001412
1413 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1415 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 +02001416
1417 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001418 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1419 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 +02001420
1421cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001423
1424 return( ret );
1425}
1426
1427/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001428 * Check and define parameters used by the comb method (see below for details)
1429 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001430#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1431#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001432#endif
1433
1434/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001435#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001436
1437/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001438#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001439
1440/*
1441 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001442 *
1443 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001444 * modified version that provides resistance to SPA by avoiding zero
1445 * digits in the representation as in [3]. We modify the method further by
1446 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001447 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001448 *
1449 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1450 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1451 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001452 *
1453 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001454 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001455 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001456 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001457 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1458 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001459 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001460static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001462{
1463 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001464 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001465
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001466 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001467
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001468 /* First get the classical comb values (except for x_d = 0) */
1469 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001470 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001472
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001473 /* Now make sure x_1 .. x_d are odd */
1474 c = 0;
1475 for( i = 1; i <= d; i++ )
1476 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001477 /* Add carry and update it */
1478 cc = x[i] & c;
1479 x[i] = x[i] ^ c;
1480 c = cc;
1481
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001482 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001483 adjust = 1 - ( x[i] & 0x01 );
1484 c |= x[i] & ( x[i-1] * adjust );
1485 x[i] = x[i] ^ ( x[i-1] * adjust );
1486 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001487 }
1488}
1489
1490/*
1491 * Precompute points for the comb method
1492 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001493 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1494 * 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 +01001495 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001496 * T must be able to hold 2^{w - 1} elements
1497 *
1498 * 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 +01001499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001500static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1501 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001502 unsigned char w, size_t d )
1503{
1504 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001505 unsigned char i, k;
1506 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001508
1509 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001510 * Set T[0] = P and
1511 * 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 +01001512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001514
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001515 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001516 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001517 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001518 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001520 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001521 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001522
1523 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001524 }
1525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001527
1528 /*
1529 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001530 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001531 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001532 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001533 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001534 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001535 j = i;
1536 while( j-- )
1537 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001538 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001539 TT[k++] = &T[i + j];
1540 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001541 }
1542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001544
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001545cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001546
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001547 return( ret );
1548}
1549
1550/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001551 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001552 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001553static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1554 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001555 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001556{
1557 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001558 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001559
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001560 /* Ignore the "sign" bit and scale down */
1561 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001562
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001563 /* Read the whole table to thwart cache-based timing attacks */
1564 for( j = 0; j < t_len; j++ )
1565 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1567 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001568 }
1569
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001570 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001571 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001572
1573cleanup:
1574 return( ret );
1575}
1576
1577/*
1578 * Core multiplication algorithm for the (modified) comb method.
1579 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001580 *
1581 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001582 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001583static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1584 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001585 const unsigned char x[], size_t d,
1586 int (*f_rng)(void *, unsigned char *, size_t),
1587 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001588{
1589 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001591 size_t i;
1592
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001594
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001595 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001596 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1598 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001599#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001600 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001601#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001603
1604 while( i-- != 0 )
1605 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1607 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1608 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001609 }
1610
1611cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001614
1615 return( ret );
1616}
1617
1618/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001619 * Multiplication using the comb method,
1620 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001621 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1623 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001624 int (*f_rng)(void *, unsigned char *, size_t),
1625 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001626{
1627 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001628 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1629 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001630 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001631 mbedtls_ecp_point *T;
1632 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001634 mbedtls_mpi_init( &M );
1635 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001636
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001637 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1639 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001640
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001641 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001642 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001643 * 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 +01001644 * (see costs of the various parts, with 1S = 1M)
1645 */
1646 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001647
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001648 /*
1649 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001650 * Just adding one avoids upping the cost of the first mul too much,
1651 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001653#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1654 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1655 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001656 if( p_eq_g )
1657 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001658#else
1659 p_eq_g = 0;
1660#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001661
1662 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001663 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001664 * (The last test is useful only for very small curves in the test suite.)
1665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1667 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001668 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001669 w = 2;
1670
1671 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001672 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001673 d = ( grp->nbits + w - 1 ) / w;
1674
1675 /*
1676 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001677 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001678 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001679 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001680
1681 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001682 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001683 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001684 if( T == NULL )
1685 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001686 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001687 goto cleanup;
1688 }
1689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001691
1692 if( p_eq_g )
1693 {
1694 grp->T = T;
1695 grp->T_size = pre_len;
1696 }
1697 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001698
1699 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001700 * Make sure M is odd (M = m or M = N - m, since N is odd)
1701 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001703 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1704 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1705 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1706 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001707
1708 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001709 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001710 */
1711 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712 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 +01001713
1714 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001715 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001716 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001718
1719 /*
1720 * Knowledge of the jacobian coordinates may leak the last few bits of the
1721 * scalar [1], and since our MPI implementation isn't constant-flow,
1722 * inversion (used for coordinate normalization) may leak the full value
1723 * of its input via side-channels [2].
1724 *
1725 * [1] https://eprint.iacr.org/2003/191
1726 * [2] https://eprint.iacr.org/2020/055
1727 *
1728 * Avoid the leak by randomizing coordinates before we normalize them.
1729 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001730#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001731 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001732#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001733 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001735
1736cleanup:
1737
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001738 /* There are two cases where T is not stored in grp:
1739 * - P != G
1740 * - An intermediate operation failed before setting grp->T
1741 * In either case, T must be freed.
1742 */
1743 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001744 {
1745 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001746 mbedtls_ecp_point_free( &T[i] );
1747 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001748 }
1749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001750 mbedtls_mpi_free( &M );
1751 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001752
1753 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001754 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001755
1756 return( ret );
1757}
1758
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001759#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001760
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001761#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001762/*
1763 * For Montgomery curves, we do all the internal arithmetic in projective
1764 * coordinates. Import/export of points uses only the x coordinates, which is
1765 * internaly represented as X / Z.
1766 *
1767 * For scalar multiplication, we'll use a Montgomery ladder.
1768 */
1769
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001770/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001771 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1772 * Cost: 1M + 1I
1773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001775{
1776 int ret;
1777
Janos Follathb0697532016-08-18 12:38:46 +01001778#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001779 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001780 {
Janos Follathc44ab972016-11-18 16:38:23 +00001781 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001782 }
Janos Follath372697b2016-10-28 16:53:11 +01001783#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001784
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1786 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1787 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001788
1789cleanup:
1790 return( ret );
1791}
1792
1793/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001794 * Randomize projective x/z coordinates:
1795 * (X, Z) -> (l X, l Z) for random l
1796 * This is sort of the reverse operation of ecp_normalize_mxz().
1797 *
1798 * This countermeasure was first suggested in [2].
1799 * Cost: 2M
1800 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001802 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1803{
1804 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001806 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001807 int count = 0;
1808
Janos Follathb0697532016-08-18 12:38:46 +01001809#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001810 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001811 {
Janos Follathc44ab972016-11-18 16:38:23 +00001812 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001813 }
Janos Follath372697b2016-10-28 16:53:11 +01001814#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001815
1816 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001818
1819 /* Generate l such that 1 < l < p */
1820 do
1821 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001822 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001823
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001824 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1825 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001826
1827 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001828 {
1829 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1830 goto cleanup;
1831 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001832 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001833 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001834
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001835 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1836 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 +01001837
1838cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001839 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001840
1841 return( ret );
1842}
1843
1844/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001845 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1846 * for Montgomery curves in x/z coordinates.
1847 *
1848 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1849 * with
1850 * d = X1
1851 * P = (X2, Z2)
1852 * Q = (X3, Z3)
1853 * R = (X4, Z4)
1854 * S = (X5, Z5)
1855 * and eliminating temporary variables tO, ..., t4.
1856 *
1857 * Cost: 5M + 4S
1858 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1860 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1861 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1862 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001863{
1864 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001865 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001866
Janos Follathb0697532016-08-18 12:38:46 +01001867#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001868 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001869 {
Janos Follathc44ab972016-11-18 16:38:23 +00001870 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001871 }
Janos Follath372697b2016-10-28 16:53:11 +01001872#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1875 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1876 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001877
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001878 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1879 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1880 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1881 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1883 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1884 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1885 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1886 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1887 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1888 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1889 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1890 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1891 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1892 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1893 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1894 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1895 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 +01001896
1897cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1899 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1900 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001901
1902 return( ret );
1903}
1904
1905/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001906 * Multiplication with Montgomery ladder in x/z coordinates,
1907 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001908 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1910 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001911 int (*f_rng)(void *, unsigned char *, size_t),
1912 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001913{
1914 int ret;
1915 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001916 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 mbedtls_ecp_point RP;
1918 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001919
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001920 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001921
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001922 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1924 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001925
1926 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1929 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001930
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001931 /* RP.X might be sligtly larger than P, so reduce it */
1932 MOD_ADD( RP.X );
1933
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001934 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001935#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001936 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001937#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001939
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001940 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001941 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001942 while( i-- > 0 )
1943 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001945 /*
1946 * if (b) R = 2R + P else R = 2R,
1947 * which is:
1948 * if (b) double_add( RP, R, RP, R )
1949 * else double_add( R, RP, R, RP )
1950 * but using safe conditional swaps to avoid leaks
1951 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001952 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1953 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1954 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1955 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1956 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001957 }
1958
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001959 /*
1960 * Knowledge of the projective coordinates may leak the last few bits of the
1961 * scalar [1], and since our MPI implementation isn't constant-flow,
1962 * inversion (used for coordinate normalization) may leak the full value
1963 * of its input via side-channels [2].
1964 *
1965 * [1] https://eprint.iacr.org/2003/191
1966 * [2] https://eprint.iacr.org/2020/055
1967 *
1968 * Avoid the leak by randomizing coordinates before we normalize them.
1969 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001970#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001971 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001972#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001973 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1974
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001975 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001976
1977cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001979
1980 return( ret );
1981}
1982
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001983#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001984
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001985/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001986 * Multiplication R = m * P
1987 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001988int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1989 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001990 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1991{
Janos Follathb0697532016-08-18 12:38:46 +01001992 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001993#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1994 char is_grp_capable = 0;
1995#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001996#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1997 ecp_drbg_context drbg_ctx;
1998
1999 ecp_drbg_init( &drbg_ctx );
2000#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002001
2002 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002003 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
2004 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002005
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002006 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
2007 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002008 return( ret );
2009
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002010#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2011 if( f_rng == NULL )
2012 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002013 const size_t m_len = ( grp->nbits + 7 ) / 8;
2014 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002015 f_rng = &ecp_drbg_random;
2016 p_rng = &drbg_ctx;
2017 }
2018#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2019
Janos Follathc44ab972016-11-18 16:38:23 +00002020#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002021 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002022 {
Janos Follathc44ab972016-11-18 16:38:23 +00002023 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002024 }
Janos Follathc44ab972016-11-18 16:38:23 +00002025#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002026
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002027#if defined(ECP_MONTGOMERY)
2028 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002029 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002030#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002031#if defined(ECP_SHORTWEIERSTRASS)
2032 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002033 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002034#endif
Janos Follathb0697532016-08-18 12:38:46 +01002035
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002036#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2037cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002038#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002039#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002040 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002041 {
Janos Follathc44ab972016-11-18 16:38:23 +00002042 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002043 }
Janos Follathc44ab972016-11-18 16:38:23 +00002044#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002045
2046#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2047 ecp_drbg_free( &drbg_ctx );
2048#endif
2049
Janos Follathb0697532016-08-18 12:38:46 +01002050 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002051}
2052
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002053#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002054/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002055 * Check that an affine point is valid as a public key,
2056 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002058static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002059{
2060 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002062
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002063 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2065 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2066 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2067 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2068 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002071
2072 /*
2073 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002074 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2077 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002078
2079 /* Special case for A = -3 */
2080 if( grp->A.p == NULL )
2081 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002082 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002083 }
2084 else
2085 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002086 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002087 }
2088
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002089 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2090 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002092 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2093 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002094
2095cleanup:
2096
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002097 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002098
2099 return( ret );
2100}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002101#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002102
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002103/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002104 * R = m * P with shortcuts for m == 1 and m == -1
2105 * NOT constant-time - ONLY for short Weierstrass!
2106 */
2107static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2108 mbedtls_ecp_point *R,
2109 const mbedtls_mpi *m,
2110 const mbedtls_ecp_point *P )
2111{
2112 int ret;
2113
2114 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2115 {
2116 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2117 }
2118 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2119 {
2120 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2121 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2122 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2123 }
2124 else
2125 {
2126 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2127 }
2128
2129cleanup:
2130 return( ret );
2131}
2132
2133/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002134 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002135 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002136 */
2137int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2138 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2139 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2140{
2141 int ret;
2142 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002143#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2144 char is_grp_capable = 0;
2145#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002146
2147 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2148 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2149
2150 mbedtls_ecp_point_init( &mP );
2151
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002152 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2153 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002154
Janos Follathc44ab972016-11-18 16:38:23 +00002155#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002156 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002157 {
Janos Follathc44ab972016-11-18 16:38:23 +00002158 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002159 }
Janos Follath430d3372016-11-03 14:25:37 +00002160
Janos Follathc44ab972016-11-18 16:38:23 +00002161#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002162 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2163 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2164
2165cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002166
Janos Follathc44ab972016-11-18 16:38:23 +00002167#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2168 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002169 {
Janos Follathc44ab972016-11-18 16:38:23 +00002170 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002171 }
Janos Follathb0697532016-08-18 12:38:46 +01002172
Janos Follathc44ab972016-11-18 16:38:23 +00002173#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002174 mbedtls_ecp_point_free( &mP );
2175
2176 return( ret );
2177}
2178
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002179
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002180#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002181/*
2182 * Check validity of a public key for Montgomery curves with x-only schemes
2183 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002185{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002186 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002187 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2188 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002189
2190 return( 0 );
2191}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002192#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002193
2194/*
2195 * Check that a point is valid as a public key
2196 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002197int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002198{
2199 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2201 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002202
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002203#if defined(ECP_MONTGOMERY)
2204 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002205 return( ecp_check_pubkey_mx( grp, pt ) );
2206#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002207#if defined(ECP_SHORTWEIERSTRASS)
2208 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002209 return( ecp_check_pubkey_sw( grp, pt ) );
2210#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002212}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002213
2214/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002216 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002218{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002219#if defined(ECP_MONTGOMERY)
2220 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002221 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002222 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002223 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2224 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2225 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002226 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002228 else
2229 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002230 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002231#endif /* ECP_MONTGOMERY */
2232#if defined(ECP_SHORTWEIERSTRASS)
2233 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002234 {
2235 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002236 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2237 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2238 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002239 else
2240 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002241 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002242#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002243
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002245}
2246
2247/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002248 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002249 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002250int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2251 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002252 int (*f_rng)(void *, unsigned char *, size_t),
2253 void *p_rng )
2254{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002255 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002256 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002257
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002258#if defined(ECP_MONTGOMERY)
2259 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002260 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002261 /* [M225] page 5 */
2262 size_t b;
2263
Janos Follath98e28a72016-05-31 14:03:54 +01002264 do {
2265 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2266 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002267
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002268 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002269 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002270 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002271 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002272 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002274
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002275 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002276 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2277 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2278 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002279 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002280#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002281
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002282#if defined(ECP_SHORTWEIERSTRASS)
2283 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002284 {
2285 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002286 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002287 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002288
2289 /*
2290 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2291 * - use the same byte ordering;
2292 * - keep the leftmost nbits bits of the generated octet string;
2293 * - try until result is in the desired range.
2294 * This also avoids any biais, which is especially important for ECDSA.
2295 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002296 do
2297 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002298 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002299 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002300
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002301 /*
2302 * Each try has at worst a probability 1/2 of failing (the msb has
2303 * a probability 1/2 of being 0, and then the result will be < N),
2304 * so after 30 tries failure probability is a most 2**(-30).
2305 *
2306 * For most curves, 1 try is enough with overwhelming probability,
2307 * since N starts with a lot of 1s in binary, but some curves
2308 * such as secp224k1 are actually very close to the worst case.
2309 */
2310 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002311 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002312
Janos Follathc3b376e2019-10-11 14:21:53 +01002313 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002314 if( ret != 0 )
2315 {
2316 goto cleanup;
2317 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002318 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002319 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002320 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002321#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002322
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002323cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002324 return( ret );
2325}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002326
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002327/*
2328 * Generate a keypair with configurable base point
2329 */
2330int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2331 const mbedtls_ecp_point *G,
2332 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2333 int (*f_rng)(void *, unsigned char *, size_t),
2334 void *p_rng )
2335{
2336 int ret;
2337
2338 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2339 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2340
2341cleanup:
2342 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002343}
2344
2345/*
2346 * Generate key pair, wrapper for conventional base point
2347 */
2348int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2349 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2350 int (*f_rng)(void *, unsigned char *, size_t),
2351 void *p_rng )
2352{
2353 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002354}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002355
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002356/*
2357 * Generate a keypair, prettier wrapper
2358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002360 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2361{
2362 int ret;
2363
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002364 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002365 return( ret );
2366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002368}
2369
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002370/*
2371 * Check a public-private key pair
2372 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002373int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002374{
2375 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 mbedtls_ecp_point Q;
2377 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002380 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2382 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2383 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002384 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002386 }
2387
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_ecp_point_init( &Q );
2389 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002390
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002391 /* mbedtls_ecp_mul() needs a non-const group... */
2392 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002393
2394 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002395 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2398 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2399 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002400 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002401 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002402 goto cleanup;
2403 }
2404
2405cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002406 mbedtls_ecp_point_free( &Q );
2407 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002408
2409 return( ret );
2410}
2411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002412#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002413
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002414#if defined(ECP_ONE_STEP_KDF)
2415/*
2416 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2417 * but unofficial ones can be found at:
2418 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2419 *
2420 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002421 * 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 +02002422 * less than one block).
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002423 */
2424#if defined(MBEDTLS_SHA512_C)
2425
2426static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002427 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
2428 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002429};
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002430static const uint8_t test_kdf_out[40] = {
2431 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
2432 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
2433 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
2434 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
2435 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002436};
2437
2438#elif defined(MBEDTLS_SHA256_C)
2439
2440static const uint8_t test_kdf_z[16] = {
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002441 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
2442 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002443};
Manuel Pégourié-Gonnard96951782020-06-22 10:18:58 +02002444static const uint8_t test_kdf_out[40] = {
2445 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
2446 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
2447 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
2448 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
2449 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002450};
2451
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002452#endif
2453
2454static int ecp_kdf_self_test( void )
2455{
2456 int ret;
2457 ecp_drbg_context kdf_ctx;
2458 mbedtls_mpi scalar;
2459 uint8_t out[sizeof( test_kdf_out )];
2460
2461 ecp_drbg_init( &kdf_ctx );
2462 mbedtls_mpi_init( &scalar );
2463 memset( out, 0, sizeof( out ) );
2464
2465 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2466 test_kdf_z, sizeof( test_kdf_z ) ) );
2467
2468 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2469 &scalar, sizeof( test_kdf_z ) ) );
2470
2471 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2472
2473 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2474 ret = -1;
2475
2476cleanup:
2477 ecp_drbg_free( &kdf_ctx );
2478 mbedtls_mpi_free( &scalar );
2479
2480 return( ret );
2481}
2482#endif /* ECP_ONE_STEP_KDF */
2483
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002484/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002485 * Checkup routine
2486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002487int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002488{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002489 int ret;
2490 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002491 mbedtls_ecp_group grp;
2492 mbedtls_ecp_point R, P;
2493 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002494 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002495 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002496 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002497 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002498 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002499 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002500 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002501 "400000000000000000000000000000000000000000000000", /* one and zeros */
2502 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2503 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002504 };
2505
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 mbedtls_ecp_group_init( &grp );
2507 mbedtls_ecp_point_init( &R );
2508 mbedtls_ecp_point_init( &P );
2509 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002510
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002511 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002513 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002514#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002515 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002516#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002517
2518 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002520
2521 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002522 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2523 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002524
2525 add_count = 0;
2526 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002527 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002528 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2529 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002530
2531 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2532 {
2533 add_c_prev = add_count;
2534 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002535 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002536 add_count = 0;
2537 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002538 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002539
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2541 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002542
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002543 if( add_count != add_c_prev ||
2544 dbl_count != dbl_c_prev ||
2545 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002546 {
2547 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002548 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002549
2550 ret = 1;
2551 goto cleanup;
2552 }
2553 }
2554
2555 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002557
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002558 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002559 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002560 /* We computed P = 2G last time, use it */
2561
2562 add_count = 0;
2563 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002564 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002565 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2566 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002567
2568 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2569 {
2570 add_c_prev = add_count;
2571 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002572 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002573 add_count = 0;
2574 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002575 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2578 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002579
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002580 if( add_count != add_c_prev ||
2581 dbl_count != dbl_c_prev ||
2582 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002583 {
2584 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002586
2587 ret = 1;
2588 goto cleanup;
2589 }
2590 }
2591
2592 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002593 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002594
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002595#if defined(ECP_ONE_STEP_KDF)
2596 if( verbose != 0 )
2597 mbedtls_printf( " ECP test #3 (internal KDF): " );
2598
2599 ret = ecp_kdf_self_test();
2600 if( ret != 0 )
2601 {
2602 if( verbose != 0 )
2603 mbedtls_printf( "failed\n" );
2604
2605 ret = 1;
2606 goto cleanup;
2607 }
2608
2609 if( verbose != 0 )
2610 mbedtls_printf( "passed\n" );
2611#endif /* ECP_ONE_STEP_KDF */
2612
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002613cleanup:
2614
2615 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002616 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002618 mbedtls_ecp_group_free( &grp );
2619 mbedtls_ecp_point_free( &R );
2620 mbedtls_ecp_point_free( &P );
2621 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002622
2623 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002624 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002625
2626 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002627}
2628
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002629#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002630
Janos Follathb0697532016-08-18 12:38:46 +01002631#endif /* !MBEDTLS_ECP_ALT */
2632
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002633#endif /* MBEDTLS_ECP_C */