blob: c13689ded52cf58c10b679e8663023c78ba12845 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010020 */
21
22/*
23 * References:
24 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010026 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010027 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010028 * RFC 4492 for the related TLS structures and constants
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020029 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020030 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010031 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020032 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020033 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
34 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
35 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010036 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020037 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010038 * render ECC resistant against Side Channel Attacks. IACR Cryptology
39 * ePrint Archive, 2004, vol. 2004, p. 342.
40 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010041 */
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020045#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020047#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010050
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000052#include "mbedtls/threading.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <string.h>
55
Janos Follathb0697532016-08-18 12:38:46 +010056#if !defined(MBEDTLS_ECP_ALT)
57
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000059#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020060#else
Rich Evans00ab4702015-02-06 13:43:58 +000061#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000062#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020064#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020066#endif
67
Janos Follath47d28f02016-11-01 13:22:05 +000068#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +010069
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020070#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020071#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020072#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020073#elif defined(MBEDTLS_CTR_DRBG_C)
74#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +020075#elif defined(MBEDTLS_SHA512_C)
76#include "mbedtls/sha512.h"
77#elif defined(MBEDTLS_SHA256_C)
78#include "mbedtls/sha256.h"
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020079#else
80#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
81#endif
82#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
83
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +010084#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
85 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +010086#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +020087#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +010088
Paul Bakker34617722014-06-13 17:20:13 +020089/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020091 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
92}
93
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010095/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +010096 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020097 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010098 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +010099static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100100#endif
101
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200102#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
103/*
104 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200105 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200106 * that people will pass non-NULL RNG when they care about side-channels, but
107 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
108 * no opportunity for the user to do anything about it.
109 *
110 * The obvious strategies for addressing that include:
111 * - change those APIs so that they take RNG arguments;
112 * - require a global RNG to be available to all crypto modules.
113 *
114 * Unfortunately those would break compatibility. So what we do instead is
115 * have our own internal DRBG instance, seeded from the secret scalar.
116 *
117 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200118 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200119 */
120
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200121#if defined(MBEDTLS_HMAC_DRBG_C)
122
123/* DRBG context type */
124typedef mbedtls_hmac_drbg_context ecp_drbg_context;
125
126/* DRBG context init */
127static inline void ecp_drbg_init( ecp_drbg_context *ctx )
128{
129 mbedtls_hmac_drbg_init( ctx );
130}
131
132/* DRBG context free */
133static inline void ecp_drbg_free( ecp_drbg_context *ctx )
134{
135 mbedtls_hmac_drbg_free( ctx );
136}
137
138/* DRBG function */
139static inline int ecp_drbg_random( void *p_rng,
140 unsigned char *output, size_t output_len )
141{
142 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
143}
144
145/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200146static int ecp_drbg_seed( ecp_drbg_context *ctx,
147 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200148{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200149 int ret;
150 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200151 /* The list starts with strong hashes */
152 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
153 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
154
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200155 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
156 secret_bytes, secret_len ) );
157
158 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
159
160cleanup:
161 mbedtls_zeroize( secret_bytes, secret_len );
162
163 return( ret );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200164}
165
166#elif defined(MBEDTLS_CTR_DRBG_C)
167
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200168/* DRBG context type */
169typedef mbedtls_ctr_drbg_context ecp_drbg_context;
170
171/* DRBG context init */
172static inline void ecp_drbg_init( ecp_drbg_context *ctx )
173{
174 mbedtls_ctr_drbg_init( ctx );
175}
176
177/* DRBG context free */
178static inline void ecp_drbg_free( ecp_drbg_context *ctx )
179{
180 mbedtls_ctr_drbg_free( ctx );
181}
182
183/* DRBG function */
184static inline int ecp_drbg_random( void *p_rng,
185 unsigned char *output, size_t output_len )
186{
187 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
188}
189
190/*
191 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
192 * we need to pass an entropy function when seeding. So we use a dummy
193 * function for that, and pass the actual entropy as customisation string.
194 * (During seeding of CTR_DRBG the entropy input and customisation string are
195 * concatenated before being used to update the secret state.)
196 */
197static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
198{
199 (void) ctx;
200 memset( out, 0, len );
201 return( 0 );
202}
203
204/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200205static int ecp_drbg_seed( ecp_drbg_context *ctx,
206 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200207{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200208 int ret;
209 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200210
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200211 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
212 secret_bytes, secret_len ) );
213
214 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
215 secret_bytes, secret_len );
216
217cleanup:
218 mbedtls_zeroize( secret_bytes, secret_len );
219
220 return( ret );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200221}
222
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200223#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200224
225/* This will be used in the self-test function */
226#define ECP_ONE_STEP_KDF
227
228/*
229 * We need to expand secret data (the scalar) into a longer stream of bytes.
230 *
231 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
232 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
233 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
234 *
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200235 * We need a basic hash abstraction layer to use whatever SHA-2 is available.
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200236 */
237#if defined(MBEDTLS_SHA512_C)
238
239#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
240#define HASH_BLOCK_BYTES ( 512 / 8 )
241
242#elif defined(MBEDTLS_SHA256_C)
243
244#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
245#define HASH_BLOCK_BYTES ( 256 / 8 )
246
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200247#endif /* SHA512/SHA256 abstraction */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200248
249/*
250 * State consists of a 32-bit counter plus the secret value.
251 *
252 * We stored them concatenated in a single buffer as that's what will get
253 * passed to the hash function.
254 */
255typedef struct {
256 size_t total_len;
257 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
258} ecp_drbg_context;
259
260static void ecp_drbg_init( ecp_drbg_context *ctx )
261{
262 memset( ctx, 0, sizeof( ecp_drbg_context ) );
263}
264
265static void ecp_drbg_free( ecp_drbg_context *ctx )
266{
267 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
268}
269
270static int ecp_drbg_seed( ecp_drbg_context *ctx,
271 const mbedtls_mpi *secret, size_t secret_len )
272{
273 ctx->total_len = 4 + secret_len;
274 memset( ctx->buf, 0, 4);
275 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
276}
277
278static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
279{
280 ecp_drbg_context *ctx = p_rng;
281 int ret;
282 size_t len_done = 0;
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200283 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200284
285 while( len_done < output_len )
286 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200287 uint8_t use_len;
288
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200289 /* This function is only called for coordinate randomisation, which
290 * happens only twice in a scalar multiplication. Each time needs a
291 * random value in the range [2, p-1], and gets it by drawing len(p)
292 * bytes from this function, and retrying up to 10 times if unlucky.
293 *
294 * So for the largest curve, each scalar multiplication draws at most
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +0200295 * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
296 * rounding that means a most 20 * 3 blocks.
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200297 *
298 * Since we don't need to draw more that 255 blocks, don't bother
299 * with carry propagation and just return an error instead. We can
300 * change that it we even need to draw more blinding values.
301 */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200302 ctx->buf[3] += 1;
303 if( ctx->buf[3] == 0 )
304 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
305
306 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
307 if( ret != 0 )
308 return( ret );
309
310 if( output_len - len_done > HASH_BLOCK_BYTES )
311 use_len = HASH_BLOCK_BYTES;
312 else
313 use_len = output_len - len_done;
314
315 memcpy( output + len_done, tmp, use_len );
316 len_done += use_len;
317 }
318
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200319 mbedtls_zeroize( tmp, sizeof( tmp ) );
320
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200321 return( 0 );
322}
323
324#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200325#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200326#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200327#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
330 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
331 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
332 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
333 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
334 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
335 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
336 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
337 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
338 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
339 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200340#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100341#endif
342
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200343#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200344#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100345#endif
346
347/*
348 * Curve types: internal for now, might be exposed later
349 */
350typedef enum
351{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200352 ECP_TYPE_NONE = 0,
353 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
354 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100355} ecp_curve_type;
356
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100357/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200358 * List of supported curves:
359 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200360 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200361 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200362 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100363 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100364 * Curves are listed in order: largest curves first, and for a given size,
365 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200366 *
367 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200368 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200370{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
372 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200373#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
375 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100376#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
378 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200379#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
381 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100382#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
384 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200385#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
387 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100388#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
390 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100391#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
393 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200394#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
396 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100397#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
399 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100400#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
402 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100403#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200405};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100406
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200407#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
408 sizeof( ecp_supported_curves[0] )
409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200411
412/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200413 * List of supported curves and associated info
414 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200416{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200417 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200418}
419
420/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100421 * List of supported curves, group ID only
422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100424{
425 static int init_done = 0;
426
427 if( ! init_done )
428 {
429 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 for( curve_info = mbedtls_ecp_curve_list();
433 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100434 curve_info++ )
435 {
436 ecp_supported_grp_id[i++] = curve_info->grp_id;
437 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100439
440 init_done = 1;
441 }
442
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200443 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100444}
445
446/*
447 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449const 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 +0200450{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 for( curve_info = mbedtls_ecp_curve_list();
454 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200455 curve_info++ )
456 {
457 if( curve_info->grp_id == grp_id )
458 return( curve_info );
459 }
460
461 return( NULL );
462}
463
464/*
465 * Get the curve info from the TLS identifier
466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200468{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 for( curve_info = mbedtls_ecp_curve_list();
472 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200473 curve_info++ )
474 {
475 if( curve_info->tls_id == tls_id )
476 return( curve_info );
477 }
478
479 return( NULL );
480}
481
482/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100483 * Get the curve info from the name
484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100486{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 for( curve_info = mbedtls_ecp_curve_list();
490 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100491 curve_info++ )
492 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200493 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100494 return( curve_info );
495 }
496
497 return( NULL );
498}
499
500/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100501 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100504{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100505 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200506 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100507
508 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200509 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100510 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200511 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100512}
513
514/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100515 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100516 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100518{
519 if( pt == NULL )
520 return;
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522 mbedtls_mpi_init( &pt->X );
523 mbedtls_mpi_init( &pt->Y );
524 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100525}
526
527/*
528 * Initialize (the components of) a group
529 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100531{
532 if( grp == NULL )
533 return;
534
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100536}
537
538/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200539 * Initialize (the components of) a key pair
540 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200541void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200542{
Paul Bakker66d5d072014-06-17 16:39:18 +0200543 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200544 return;
545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 mbedtls_ecp_group_init( &key->grp );
547 mbedtls_mpi_init( &key->d );
548 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200549}
550
551/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100552 * Unallocate (the components of) a point
553 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100555{
556 if( pt == NULL )
557 return;
558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 mbedtls_mpi_free( &( pt->X ) );
560 mbedtls_mpi_free( &( pt->Y ) );
561 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100562}
563
564/*
565 * Unallocate (the components of) a group
566 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100568{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200569 size_t i;
570
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100571 if( grp == NULL )
572 return;
573
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100574 if( grp->h != 1 )
575 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 mbedtls_mpi_free( &grp->P );
577 mbedtls_mpi_free( &grp->A );
578 mbedtls_mpi_free( &grp->B );
579 mbedtls_ecp_point_free( &grp->G );
580 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100581 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200582
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200583 if( grp->T != NULL )
584 {
585 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_ecp_point_free( &grp->T[i] );
587 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200588 }
589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100591}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100592
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100593/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200594 * Unallocate (the components of) a key pair
595 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200597{
Paul Bakker66d5d072014-06-17 16:39:18 +0200598 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200599 return;
600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 mbedtls_ecp_group_free( &key->grp );
602 mbedtls_mpi_free( &key->d );
603 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200604}
605
606/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200607 * Copy the contents of a point
608 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200610{
611 int ret;
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
614 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
615 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200616
617cleanup:
618 return( ret );
619}
620
621/*
622 * Copy the contents of a group object
623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200624int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200625{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200626 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200627}
628
629/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100630 * Set point to zero
631 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100633{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100634 int ret;
635
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200636 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
637 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
638 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100639
640cleanup:
641 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100642}
643
644/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100645 * Tell if a point is zero
646 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100648{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100650}
651
652/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700653 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200654 */
655int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
656 const mbedtls_ecp_point *Q )
657{
658 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
659 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
660 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
661 {
662 return( 0 );
663 }
664
665 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
666}
667
668/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100669 * Import a non-zero point from ASCII strings
670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100672 const char *x, const char *y )
673{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100674 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100675
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200676 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
677 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
678 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100679
680cleanup:
681 return( ret );
682}
683
684/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100685 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100688 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100689 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100690{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200691 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100692 size_t plen;
693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
695 format != MBEDTLS_ECP_PF_COMPRESSED )
696 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100697
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100698 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100699 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100702 {
703 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100705
706 buf[0] = 0x00;
707 *olen = 1;
708
709 return( 0 );
710 }
711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100715 {
716 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100717
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100718 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100720
721 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
723 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100724 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100726 {
727 *olen = plen + 1;
728
729 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
733 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100734 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100735
736cleanup:
737 return( ret );
738}
739
740/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100741 * Import a point from unsigned binary data (SEC1 2.3.4)
742 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100744 const unsigned char *buf, size_t ilen )
745{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100746 int ret;
747 size_t plen;
748
Paul Bakker82788fb2014-10-20 13:59:19 +0200749 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200751
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100752 if( buf[0] == 0x00 )
753 {
754 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100756 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100758 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100761
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100762 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100764
765 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100767
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200768 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
769 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
770 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100771
772cleanup:
773 return( ret );
774}
775
776/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100777 * Import a point from a TLS ECPoint record (RFC 4492)
778 * struct {
779 * opaque point <1..2^8-1>;
780 * } ECPoint;
781 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100783 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100784{
785 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100786 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100787
788 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200789 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100790 */
791 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100793
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100794 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100795 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100797
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100798 /*
799 * Save buffer start for read_binary and update buf
800 */
801 buf_start = *buf;
802 *buf += data_len;
803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100805}
806
807/*
808 * Export a point as a TLS ECPoint record (RFC 4492)
809 * struct {
810 * opaque point <1..2^8-1>;
811 * } ECPoint;
812 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100814 int format, size_t *olen,
815 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100816{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100817 int ret;
818
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100819 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100820 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100821 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100822 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100824
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200825 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100826 olen, buf + 1, blen - 1) ) != 0 )
827 return( ret );
828
829 /*
830 * write length to the first byte and update total length
831 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200832 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100833 ++*olen;
834
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200835 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100836}
837
838/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100839 * Set a group from an ECParameters record (RFC 4492)
840 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841int 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 +0100842{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200843 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100845
846 /*
847 * We expect at least three bytes (see below)
848 */
849 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100851
852 /*
853 * First byte is curve_type; only named_curve is handled
854 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
856 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100857
858 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100859 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100860 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200861 tls_id = *(*buf)++;
862 tls_id <<= 8;
863 tls_id |= *(*buf)++;
864
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
866 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200867
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200868 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100869}
870
871/*
872 * Write the ECParameters record corresponding to a group (RFC 4492)
873 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100875 unsigned char *buf, size_t blen )
876{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
880 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200881
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100882 /*
883 * We are going to write 3 bytes (see below)
884 */
885 *olen = 3;
886 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200887 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100888
889 /*
890 * First byte is curve_type, always named_curve
891 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200892 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100893
894 /*
895 * Next two bytes are the namedcurve value
896 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200897 buf[0] = curve_info->tls_id >> 8;
898 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100899
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200900 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100901}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100902
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200903/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200904 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
905 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200906 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907 * 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 +0200908 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200909static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200910{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200911 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200912
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200913 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200914 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200915
916 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200917 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200918 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200919 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200921 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200922
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200924
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200925 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200926 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
927 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200930 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200931 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200932
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200933cleanup:
934 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200935}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200936
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100937/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100938 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100939 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100940 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941 * 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 +0100942 * bring the result back to this range.
943 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100944 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100945 */
946
947/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948 * 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 +0100949 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100951#define INC_MUL_COUNT mul_count++;
952#else
953#define INC_MUL_COUNT
954#endif
955
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100957 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100958
959/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200961 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100962 */
963#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
965 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100966
967/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968 * 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 +0200969 * We known P, N and the result are positive, so sub_abs is correct, and
970 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100971 */
972#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
974 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100975
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200976#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100977/*
978 * For curves in short Weierstrass form, we do all the internal operations in
979 * Jacobian coordinates.
980 *
981 * For multiplication, we'll use a comb method with coutermeasueres against
982 * SPA, hence timing attacks.
983 */
984
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100985/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100986 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100987 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100988 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200989static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100990{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100991 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100993
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100995 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100996
Janos Follathb0697532016-08-18 12:38:46 +0100997#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000998 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100999 {
Janos Follathc44ab972016-11-18 16:38:23 +00001000 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +01001001 }
Janos Follath372697b2016-10-28 16:53:11 +01001002#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001004
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001005 /*
1006 * X = X / Z^2 mod p
1007 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001008 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1009 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1010 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 +01001011
1012 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001013 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001014 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1016 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 +01001017
1018 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001019 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001020 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001022
1023cleanup:
1024
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001026
1027 return( ret );
1028}
1029
1030/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001031 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001032 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001033 * (See for example Cohen's "A Course in Computational Algebraic Number
1034 * Theory", Algorithm 10.3.4.)
1035 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001036 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001037 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001038 *
1039 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001040 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1042 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001043{
1044 int ret;
1045 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001046 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001047
1048 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001049 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001050
Janos Follathb0697532016-08-18 12:38:46 +01001051#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001052 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001053 {
Janos Follathc44ab972016-11-18 16:38:23 +00001054 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001055 }
1056#endif
1057
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001058 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001059 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001061 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001062
1063 /*
1064 * c[i] = Z_0 * ... * Z_i
1065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001066 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001067 for( i = 1; i < t_len; i++ )
1068 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001069 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001070 MOD_MUL( c[i] );
1071 }
1072
1073 /*
1074 * u = 1 / (Z_0 * ... * Z_n) mod P
1075 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001076 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001077
1078 for( i = t_len - 1; ; i-- )
1079 {
1080 /*
1081 * Zi = 1 / Z_i mod p
1082 * u = 1 / (Z_0 * ... * Z_i) mod P
1083 */
1084 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001086 }
1087 else
1088 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001089 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1090 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001091 }
1092
1093 /*
1094 * proceed as in normalize()
1095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1097 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1098 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1099 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 +01001100
1101 /*
1102 * Post-precessing: reclaim some memory by shrinking coordinates
1103 * - not storing Z (always 1)
1104 * - shrinking other coordinates, but still keeping the same number of
1105 * limbs as P, as otherwise it will too likely be regrown too fast.
1106 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001107 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1108 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1109 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001110
1111 if( i == 0 )
1112 break;
1113 }
1114
1115cleanup:
1116
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001118 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 mbedtls_mpi_free( &c[i] );
1120 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001121
1122 return( ret );
1123}
1124
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001125/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001126 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1127 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1128 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001129static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1130 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001131 unsigned char inv )
1132{
1133 int ret;
1134 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001136
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001137 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001138
1139 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1141 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1142 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001143
1144cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001145 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001146
1147 return( ret );
1148}
1149
1150/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001151 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001152 *
Peter Dettmance661b22015-02-07 14:43:51 +07001153 * 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 +01001154 *
Peter Dettmance661b22015-02-07 14:43:51 +07001155 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1156 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1157 *
1158 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1159 *
1160 * Cost: 1D := 3M + 4S (A == 0)
1161 * 4M + 4S (A == -3)
1162 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001163 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001164static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1165 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001166{
1167 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001168 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001170#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001171 dbl_count++;
1172#endif
1173
Janos Follathb0697532016-08-18 12:38:46 +01001174#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001175 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001176 {
Janos Follathc44ab972016-11-18 16:38:23 +00001177 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001178 }
Janos Follath372697b2016-10-28 16:53:11 +01001179#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001180
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001181 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 +01001182
1183 /* Special case for A = -3 */
1184 if( grp->A.p == NULL )
1185 {
Peter Dettmance661b22015-02-07 14:43:51 +07001186 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001187 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1188 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1189 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1190 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1191 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001192 }
1193 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001194 {
Peter Dettmance661b22015-02-07 14:43:51 +07001195 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001198
1199 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001200 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001201 {
1202 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001203 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1204 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1205 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1206 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001207 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001208 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001209
Peter Dettmance661b22015-02-07 14:43:51 +07001210 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001211 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1212 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1213 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001215
Peter Dettmance661b22015-02-07 14:43:51 +07001216 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001217 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1218 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001219
1220 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001221 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1223 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001224
1225 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1227 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1228 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001229
1230 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001231 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1232 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001233
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001234 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1235 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1236 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001237
1238cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001239 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 +02001240
1241 return( ret );
1242}
1243
1244/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001245 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001246 *
1247 * The coordinates of Q must be normalized (= affine),
1248 * but those of P don't need to. R is not normalized.
1249 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001250 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001251 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001252 * - at each step, P, Q and R are multiples of the base point, the factor
1253 * being less than its order, so none of them is zero;
1254 * - Q is an odd multiple of the base point, P an even multiple,
1255 * due to the choice of precomputed points in the modified comb method.
1256 * So branches for these cases do not leak secret information.
1257 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001258 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1259 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001260 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001261 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1263 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001264{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001265 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001267
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001268#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001269 add_count++;
1270#endif
1271
Janos Follathb0697532016-08-18 12:38:46 +01001272#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001273 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001274 {
Janos Follathc44ab972016-11-18 16:38:23 +00001275 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001276 }
Janos Follath372697b2016-10-28 16:53:11 +01001277#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001278
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001279 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001280 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001281 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001282 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1283 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001285 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1286 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001287
1288 /*
1289 * Make sure Q coordinates are normalized
1290 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1292 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1295 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001297 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1298 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1299 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1300 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1301 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1302 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001303
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001304 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001306 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001307 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001308 {
1309 ret = ecp_double_jac( grp, R, P );
1310 goto cleanup;
1311 }
1312 else
1313 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001315 goto cleanup;
1316 }
1317 }
1318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001319 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1320 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1321 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1327 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1328 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1330 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001332 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1334 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001335
1336cleanup:
1337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001338 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1339 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001340
1341 return( ret );
1342}
1343
1344/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001345 * Randomize jacobian coordinates:
1346 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001347 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001348 *
1349 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001352 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1353{
1354 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001355 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001356 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001357 int count = 0;
1358
Janos Follathb0697532016-08-18 12:38:46 +01001359#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001360 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001361 {
Janos Follathc44ab972016-11-18 16:38:23 +00001362 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001363 }
Janos Follath372697b2016-10-28 16:53:11 +01001364#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001365
1366 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001367 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001368
1369 /* Generate l such that 1 < l < p */
1370 do
1371 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001373
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1375 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001376
1377 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001378 {
1379 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1380 goto cleanup;
1381 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001382 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001384
1385 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001386 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 +02001387
1388 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1390 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 +02001391
1392 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1394 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 +02001395
1396cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001397 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001398
1399 return( ret );
1400}
1401
1402/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001403 * Check and define parameters used by the comb method (see below for details)
1404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001405#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1406#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001407#endif
1408
1409/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001411
1412/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001413#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001414
1415/*
1416 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001417 *
1418 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001419 * modified version that provides resistance to SPA by avoiding zero
1420 * digits in the representation as in [3]. We modify the method further by
1421 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001422 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001423 *
1424 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1425 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1426 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001427 *
1428 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001429 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001430 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001431 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001432 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1433 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001434 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001435static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001437{
1438 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001439 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001440
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001441 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001442
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001443 /* First get the classical comb values (except for x_d = 0) */
1444 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001445 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001447
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001448 /* Now make sure x_1 .. x_d are odd */
1449 c = 0;
1450 for( i = 1; i <= d; i++ )
1451 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001452 /* Add carry and update it */
1453 cc = x[i] & c;
1454 x[i] = x[i] ^ c;
1455 c = cc;
1456
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001457 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001458 adjust = 1 - ( x[i] & 0x01 );
1459 c |= x[i] & ( x[i-1] * adjust );
1460 x[i] = x[i] ^ ( x[i-1] * adjust );
1461 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001462 }
1463}
1464
1465/*
1466 * Precompute points for the comb method
1467 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001468 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1469 * 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 +01001470 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001471 * T must be able to hold 2^{w - 1} elements
1472 *
1473 * 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 +01001474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1476 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001477 unsigned char w, size_t d )
1478{
1479 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001480 unsigned char i, k;
1481 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001482 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001483
1484 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001485 * Set T[0] = P and
1486 * 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 +01001487 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001488 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001489
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001490 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001491 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001492 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001493 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001495 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001496 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001497
1498 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001499 }
1500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001501 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001502
1503 /*
1504 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001505 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001506 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001507 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001508 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001509 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001510 j = i;
1511 while( j-- )
1512 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001513 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001514 TT[k++] = &T[i + j];
1515 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001516 }
1517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001518 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001519
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001520cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001521
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001522 return( ret );
1523}
1524
1525/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001526 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001528static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1529 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001530 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001531{
1532 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001533 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001534
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001535 /* Ignore the "sign" bit and scale down */
1536 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001537
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001538 /* Read the whole table to thwart cache-based timing attacks */
1539 for( j = 0; j < t_len; j++ )
1540 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001541 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1542 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001543 }
1544
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001545 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001546 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001547
1548cleanup:
1549 return( ret );
1550}
1551
1552/*
1553 * Core multiplication algorithm for the (modified) comb method.
1554 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001555 *
1556 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001557 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001558static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1559 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001560 const unsigned char x[], size_t d,
1561 int (*f_rng)(void *, unsigned char *, size_t),
1562 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001563{
1564 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001566 size_t i;
1567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001569
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001570 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001571 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001572 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1573 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001574#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001575 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001576#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001578
1579 while( i-- != 0 )
1580 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1582 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1583 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001584 }
1585
1586cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001589
1590 return( ret );
1591}
1592
1593/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001594 * Multiplication using the comb method,
1595 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001596 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1598 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001599 int (*f_rng)(void *, unsigned char *, size_t),
1600 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001601{
1602 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001603 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1604 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001605 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606 mbedtls_ecp_point *T;
1607 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 mbedtls_mpi_init( &M );
1610 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001611
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001612 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001613 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1614 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001615
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001616 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001617 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001618 * 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 +01001619 * (see costs of the various parts, with 1S = 1M)
1620 */
1621 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001622
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001623 /*
1624 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001625 * Just adding one avoids upping the cost of the first mul too much,
1626 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001628#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1629 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1630 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001631 if( p_eq_g )
1632 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001633#else
1634 p_eq_g = 0;
1635#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001636
1637 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001638 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001639 * (The last test is useful only for very small curves in the test suite.)
1640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001641 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1642 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001643 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001644 w = 2;
1645
1646 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001647 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001648 d = ( grp->nbits + w - 1 ) / w;
1649
1650 /*
1651 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001652 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001653 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001654 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001655
1656 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001657 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001658 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001659 if( T == NULL )
1660 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001661 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001662 goto cleanup;
1663 }
1664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001665 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001666
1667 if( p_eq_g )
1668 {
1669 grp->T = T;
1670 grp->T_size = pre_len;
1671 }
1672 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001673
1674 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001675 * Make sure M is odd (M = m or M = N - m, since N is odd)
1676 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001677 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001678 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1680 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1681 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001682
1683 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001684 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001685 */
1686 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 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 +01001688
1689 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001690 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001691 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001693
1694 /*
1695 * Knowledge of the jacobian coordinates may leak the last few bits of the
1696 * scalar [1], and since our MPI implementation isn't constant-flow,
1697 * inversion (used for coordinate normalization) may leak the full value
1698 * of its input via side-channels [2].
1699 *
1700 * [1] https://eprint.iacr.org/2003/191
1701 * [2] https://eprint.iacr.org/2020/055
1702 *
1703 * Avoid the leak by randomizing coordinates before we normalize them.
1704 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001705#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001706 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001707#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001708 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001709 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001710
1711cleanup:
1712
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001713 /* There are two cases where T is not stored in grp:
1714 * - P != G
1715 * - An intermediate operation failed before setting grp->T
1716 * In either case, T must be freed.
1717 */
1718 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001719 {
1720 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 mbedtls_ecp_point_free( &T[i] );
1722 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001723 }
1724
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 mbedtls_mpi_free( &M );
1726 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001727
1728 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001729 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001730
1731 return( ret );
1732}
1733
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001734#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001735
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001736#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001737/*
1738 * For Montgomery curves, we do all the internal arithmetic in projective
1739 * coordinates. Import/export of points uses only the x coordinates, which is
1740 * internaly represented as X / Z.
1741 *
1742 * For scalar multiplication, we'll use a Montgomery ladder.
1743 */
1744
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001745/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001746 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1747 * Cost: 1M + 1I
1748 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001749static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001750{
1751 int ret;
1752
Janos Follathb0697532016-08-18 12:38:46 +01001753#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001754 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001755 {
Janos Follathc44ab972016-11-18 16:38:23 +00001756 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001757 }
Janos Follath372697b2016-10-28 16:53:11 +01001758#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001759
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001760 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1761 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1762 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001763
1764cleanup:
1765 return( ret );
1766}
1767
1768/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001769 * Randomize projective x/z coordinates:
1770 * (X, Z) -> (l X, l Z) for random l
1771 * This is sort of the reverse operation of ecp_normalize_mxz().
1772 *
1773 * This countermeasure was first suggested in [2].
1774 * Cost: 2M
1775 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001777 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1778{
1779 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001781 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001782 int count = 0;
1783
Janos Follathb0697532016-08-18 12:38:46 +01001784#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001785 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001786 {
Janos Follathc44ab972016-11-18 16:38:23 +00001787 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001788 }
Janos Follath372697b2016-10-28 16:53:11 +01001789#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001790
1791 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001792 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001793
1794 /* Generate l such that 1 < l < p */
1795 do
1796 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001797 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001798
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001799 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1800 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001801
1802 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001803 {
1804 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1805 goto cleanup;
1806 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001807 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001809
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1811 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 +01001812
1813cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001814 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001815
1816 return( ret );
1817}
1818
1819/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001820 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1821 * for Montgomery curves in x/z coordinates.
1822 *
1823 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1824 * with
1825 * d = X1
1826 * P = (X2, Z2)
1827 * Q = (X3, Z3)
1828 * R = (X4, Z4)
1829 * S = (X5, Z5)
1830 * and eliminating temporary variables tO, ..., t4.
1831 *
1832 * Cost: 5M + 4S
1833 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001834static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1835 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1836 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1837 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001838{
1839 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001840 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001841
Janos Follathb0697532016-08-18 12:38:46 +01001842#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001843 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001844 {
Janos Follathc44ab972016-11-18 16:38:23 +00001845 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001846 }
Janos Follath372697b2016-10-28 16:53:11 +01001847#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1850 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1851 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001852
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001853 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1858 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1869 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1870 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 +01001871
1872cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001873 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1874 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1875 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001876
1877 return( ret );
1878}
1879
1880/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001881 * Multiplication with Montgomery ladder in x/z coordinates,
1882 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001883 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001884static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1885 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001886 int (*f_rng)(void *, unsigned char *, size_t),
1887 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001888{
1889 int ret;
1890 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001891 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 mbedtls_ecp_point RP;
1893 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001894
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001895 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001896
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001897 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1899 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001900
1901 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001902 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1903 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1904 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001905
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001906 /* RP.X might be sligtly larger than P, so reduce it */
1907 MOD_ADD( RP.X );
1908
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001909 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001910#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001911 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001912#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001914
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001915 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001916 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001917 while( i-- > 0 )
1918 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001919 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001920 /*
1921 * if (b) R = 2R + P else R = 2R,
1922 * which is:
1923 * if (b) double_add( RP, R, RP, R )
1924 * else double_add( R, RP, R, RP )
1925 * but using safe conditional swaps to avoid leaks
1926 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001927 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1929 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1930 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1931 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001932 }
1933
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001934 /*
1935 * Knowledge of the projective coordinates may leak the last few bits of the
1936 * scalar [1], and since our MPI implementation isn't constant-flow,
1937 * inversion (used for coordinate normalization) may leak the full value
1938 * of its input via side-channels [2].
1939 *
1940 * [1] https://eprint.iacr.org/2003/191
1941 * [2] https://eprint.iacr.org/2020/055
1942 *
1943 * Avoid the leak by randomizing coordinates before we normalize them.
1944 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001945#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001946 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001947#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001948 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1949
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001950 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001951
1952cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001953 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001954
1955 return( ret );
1956}
1957
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001958#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001959
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001960/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001961 * Multiplication R = m * P
1962 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001963int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1964 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001965 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1966{
Janos Follathb0697532016-08-18 12:38:46 +01001967 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001968#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1969 char is_grp_capable = 0;
1970#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001971#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1972 ecp_drbg_context drbg_ctx;
1973
1974 ecp_drbg_init( &drbg_ctx );
1975#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001976
1977 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001978 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1979 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001980
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001981 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1982 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001983 return( ret );
1984
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001985#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1986 if( f_rng == NULL )
1987 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02001988 const size_t m_len = ( grp->nbits + 7 ) / 8;
1989 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001990 f_rng = &ecp_drbg_random;
1991 p_rng = &drbg_ctx;
1992 }
1993#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
1994
Janos Follathc44ab972016-11-18 16:38:23 +00001995#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001996 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001997 {
Janos Follathc44ab972016-11-18 16:38:23 +00001998 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01001999 }
Janos Follathc44ab972016-11-18 16:38:23 +00002000#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002001
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002002#if defined(ECP_MONTGOMERY)
2003 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002004 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002005#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002006#if defined(ECP_SHORTWEIERSTRASS)
2007 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002008 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002009#endif
Janos Follathb0697532016-08-18 12:38:46 +01002010
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002011#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2012cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002013#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002014#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002015 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002016 {
Janos Follathc44ab972016-11-18 16:38:23 +00002017 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002018 }
Janos Follathc44ab972016-11-18 16:38:23 +00002019#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002020
2021#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2022 ecp_drbg_free( &drbg_ctx );
2023#endif
2024
Janos Follathb0697532016-08-18 12:38:46 +01002025 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002026}
2027
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002028#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002029/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002030 * Check that an affine point is valid as a public key,
2031 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002032 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002033static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002034{
2035 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002037
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002038 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2040 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2041 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2042 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2043 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002044
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002046
2047 /*
2048 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002049 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002050 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2052 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002053
2054 /* Special case for A = -3 */
2055 if( grp->A.p == NULL )
2056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002058 }
2059 else
2060 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002061 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002062 }
2063
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002064 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2065 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002066
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2068 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002069
2070cleanup:
2071
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002072 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002073
2074 return( ret );
2075}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002076#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002077
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002078/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002079 * R = m * P with shortcuts for m == 1 and m == -1
2080 * NOT constant-time - ONLY for short Weierstrass!
2081 */
2082static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2083 mbedtls_ecp_point *R,
2084 const mbedtls_mpi *m,
2085 const mbedtls_ecp_point *P )
2086{
2087 int ret;
2088
2089 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2090 {
2091 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2092 }
2093 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2094 {
2095 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2096 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2097 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2098 }
2099 else
2100 {
2101 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2102 }
2103
2104cleanup:
2105 return( ret );
2106}
2107
2108/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002109 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002110 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002111 */
2112int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2113 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2114 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2115{
2116 int ret;
2117 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002118#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2119 char is_grp_capable = 0;
2120#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002121
2122 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2123 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2124
2125 mbedtls_ecp_point_init( &mP );
2126
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002127 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2128 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002129
Janos Follathc44ab972016-11-18 16:38:23 +00002130#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002131 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002132 {
Janos Follathc44ab972016-11-18 16:38:23 +00002133 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002134 }
Janos Follath430d3372016-11-03 14:25:37 +00002135
Janos Follathc44ab972016-11-18 16:38:23 +00002136#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002137 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2138 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2139
2140cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002141
Janos Follathc44ab972016-11-18 16:38:23 +00002142#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2143 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002144 {
Janos Follathc44ab972016-11-18 16:38:23 +00002145 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002146 }
Janos Follathb0697532016-08-18 12:38:46 +01002147
Janos Follathc44ab972016-11-18 16:38:23 +00002148#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002149 mbedtls_ecp_point_free( &mP );
2150
2151 return( ret );
2152}
2153
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002154
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002155#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002156/*
2157 * Check validity of a public key for Montgomery curves with x-only schemes
2158 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002159static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002160{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002161 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002162 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2163 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002164
2165 return( 0 );
2166}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002167#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002168
2169/*
2170 * Check that a point is valid as a public key
2171 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002172int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002173{
2174 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002175 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2176 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002177
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002178#if defined(ECP_MONTGOMERY)
2179 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002180 return( ecp_check_pubkey_mx( grp, pt ) );
2181#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002182#if defined(ECP_SHORTWEIERSTRASS)
2183 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002184 return( ecp_check_pubkey_sw( grp, pt ) );
2185#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002187}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002188
2189/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002192int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002193{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002194#if defined(ECP_MONTGOMERY)
2195 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002196 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002197 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2199 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2200 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002201 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002202 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002203 else
2204 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002205 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002206#endif /* ECP_MONTGOMERY */
2207#if defined(ECP_SHORTWEIERSTRASS)
2208 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002209 {
2210 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2212 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2213 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002214 else
2215 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002216 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002217#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002220}
2221
2222/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002223 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002224 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002225int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2226 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002227 int (*f_rng)(void *, unsigned char *, size_t),
2228 void *p_rng )
2229{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002230 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002231 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002232
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002233#if defined(ECP_MONTGOMERY)
2234 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002235 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002236 /* [M225] page 5 */
2237 size_t b;
2238
Janos Follath98e28a72016-05-31 14:03:54 +01002239 do {
2240 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2241 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002242
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002243 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002244 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002245 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002247 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002248 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002249
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002250 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002251 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2252 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2253 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002254 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002255#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002256
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002257#if defined(ECP_SHORTWEIERSTRASS)
2258 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002259 {
2260 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002261 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002262 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002263
2264 /*
2265 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2266 * - use the same byte ordering;
2267 * - keep the leftmost nbits bits of the generated octet string;
2268 * - try until result is in the desired range.
2269 * This also avoids any biais, which is especially important for ECDSA.
2270 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002271 do
2272 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002273 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002274 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002275
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002276 /*
2277 * Each try has at worst a probability 1/2 of failing (the msb has
2278 * a probability 1/2 of being 0, and then the result will be < N),
2279 * so after 30 tries failure probability is a most 2**(-30).
2280 *
2281 * For most curves, 1 try is enough with overwhelming probability,
2282 * since N starts with a lot of 1s in binary, but some curves
2283 * such as secp224k1 are actually very close to the worst case.
2284 */
2285 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002286 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002287
Janos Follathc3b376e2019-10-11 14:21:53 +01002288 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002289 if( ret != 0 )
2290 {
2291 goto cleanup;
2292 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002293 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002294 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002295 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002296#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002297
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002298cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002299 return( ret );
2300}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002301
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002302/*
2303 * Generate a keypair with configurable base point
2304 */
2305int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2306 const mbedtls_ecp_point *G,
2307 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2308 int (*f_rng)(void *, unsigned char *, size_t),
2309 void *p_rng )
2310{
2311 int ret;
2312
2313 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2314 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2315
2316cleanup:
2317 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002318}
2319
2320/*
2321 * Generate key pair, wrapper for conventional base point
2322 */
2323int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2324 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2325 int (*f_rng)(void *, unsigned char *, size_t),
2326 void *p_rng )
2327{
2328 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002329}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002330
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002331/*
2332 * Generate a keypair, prettier wrapper
2333 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002334int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002335 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2336{
2337 int ret;
2338
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002339 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002340 return( ret );
2341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002343}
2344
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002345/*
2346 * Check a public-private key pair
2347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002348int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002349{
2350 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 mbedtls_ecp_point Q;
2352 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002353
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002355 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2357 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2358 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002359 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002361 }
2362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 mbedtls_ecp_point_init( &Q );
2364 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 /* mbedtls_ecp_mul() needs a non-const group... */
2367 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002368
2369 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2373 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2374 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002375 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002376 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002377 goto cleanup;
2378 }
2379
2380cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 mbedtls_ecp_point_free( &Q );
2382 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002383
2384 return( ret );
2385}
2386
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002387#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002388
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002389#if defined(ECP_ONE_STEP_KDF)
2390/*
2391 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2392 * but unofficial ones can be found at:
2393 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2394 *
2395 * We only use the ones with empty fixedInfo, and for brevity's sake, only
Manuel Pégourié-Gonnard13810912020-06-18 12:14:34 +02002396 * 32-bytes output (with SHA-256 that's exactly one block, and with SHA-512
2397 * less than one block).
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002398 */
2399#if defined(MBEDTLS_SHA512_C)
2400
2401static const uint8_t test_kdf_z[16] = {
2402 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
2403 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
2404};
2405static const uint8_t test_kdf_out[32] = {
2406 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
2407 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
2408 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
2409 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
2410};
2411
2412#elif defined(MBEDTLS_SHA256_C)
2413
2414static const uint8_t test_kdf_z[16] = {
2415 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
2416 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
2417};
2418static const uint8_t test_kdf_out[32] = {
2419 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
2420 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
2421 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
2422 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
2423};
2424
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002425#endif
2426
2427static int ecp_kdf_self_test( void )
2428{
2429 int ret;
2430 ecp_drbg_context kdf_ctx;
2431 mbedtls_mpi scalar;
2432 uint8_t out[sizeof( test_kdf_out )];
2433
2434 ecp_drbg_init( &kdf_ctx );
2435 mbedtls_mpi_init( &scalar );
2436 memset( out, 0, sizeof( out ) );
2437
2438 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2439 test_kdf_z, sizeof( test_kdf_z ) ) );
2440
2441 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2442 &scalar, sizeof( test_kdf_z ) ) );
2443
2444 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2445
2446 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2447 ret = -1;
2448
2449cleanup:
2450 ecp_drbg_free( &kdf_ctx );
2451 mbedtls_mpi_free( &scalar );
2452
2453 return( ret );
2454}
2455#endif /* ECP_ONE_STEP_KDF */
2456
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002457/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002458 * Checkup routine
2459 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002460int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002461{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002462 int ret;
2463 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002464 mbedtls_ecp_group grp;
2465 mbedtls_ecp_point R, P;
2466 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002467 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002468 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002469 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002470 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002471 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002472 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002473 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002474 "400000000000000000000000000000000000000000000000", /* one and zeros */
2475 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2476 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002477 };
2478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479 mbedtls_ecp_group_init( &grp );
2480 mbedtls_ecp_point_init( &R );
2481 mbedtls_ecp_point_init( &P );
2482 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002483
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002484 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002485#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002486 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002487#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002488 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002489#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002490
2491 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002493
2494 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2496 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002497
2498 add_count = 0;
2499 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002500 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002501 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2502 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002503
2504 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2505 {
2506 add_c_prev = add_count;
2507 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002508 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002509 add_count = 0;
2510 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002511 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002512
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002513 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2514 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002515
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002516 if( add_count != add_c_prev ||
2517 dbl_count != dbl_c_prev ||
2518 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002519 {
2520 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002521 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002522
2523 ret = 1;
2524 goto cleanup;
2525 }
2526 }
2527
2528 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002529 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002530
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002531 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002533 /* We computed P = 2G last time, use it */
2534
2535 add_count = 0;
2536 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002537 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002538 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2539 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002540
2541 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2542 {
2543 add_c_prev = add_count;
2544 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002545 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002546 add_count = 0;
2547 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002548 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002549
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002550 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2551 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002552
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002553 if( add_count != add_c_prev ||
2554 dbl_count != dbl_c_prev ||
2555 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002556 {
2557 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002558 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002559
2560 ret = 1;
2561 goto cleanup;
2562 }
2563 }
2564
2565 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002566 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002567
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002568#if defined(ECP_ONE_STEP_KDF)
2569 if( verbose != 0 )
2570 mbedtls_printf( " ECP test #3 (internal KDF): " );
2571
2572 ret = ecp_kdf_self_test();
2573 if( ret != 0 )
2574 {
2575 if( verbose != 0 )
2576 mbedtls_printf( "failed\n" );
2577
2578 ret = 1;
2579 goto cleanup;
2580 }
2581
2582 if( verbose != 0 )
2583 mbedtls_printf( "passed\n" );
2584#endif /* ECP_ONE_STEP_KDF */
2585
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002586cleanup:
2587
2588 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002589 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002590
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_ecp_group_free( &grp );
2592 mbedtls_ecp_point_free( &R );
2593 mbedtls_ecp_point_free( &P );
2594 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002595
2596 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002597 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002598
2599 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002600}
2601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002603
Janos Follathb0697532016-08-18 12:38:46 +01002604#endif /* !MBEDTLS_ECP_ALT */
2605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002606#endif /* MBEDTLS_ECP_C */