blob: 8da65ad1d1f2120182978779a68fa2754217a709 [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"
79#elif defined(MBEDTLS_SHA1_C)
80#include "mbedtls/sha1.h"
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020081#else
82#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
83#endif
84#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
85
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +010086#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
87 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +010088#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +020089#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +010090
Paul Bakker34617722014-06-13 17:20:13 +020091/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020093 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
94}
95
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010097/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +010098 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020099 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100100 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100101static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100102#endif
103
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200104#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
105/*
106 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200107 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200108 * that people will pass non-NULL RNG when they care about side-channels, but
109 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
110 * no opportunity for the user to do anything about it.
111 *
112 * The obvious strategies for addressing that include:
113 * - change those APIs so that they take RNG arguments;
114 * - require a global RNG to be available to all crypto modules.
115 *
116 * Unfortunately those would break compatibility. So what we do instead is
117 * have our own internal DRBG instance, seeded from the secret scalar.
118 *
119 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200120 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200121 */
122
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200123#if defined(MBEDTLS_HMAC_DRBG_C)
124
125/* DRBG context type */
126typedef mbedtls_hmac_drbg_context ecp_drbg_context;
127
128/* DRBG context init */
129static inline void ecp_drbg_init( ecp_drbg_context *ctx )
130{
131 mbedtls_hmac_drbg_init( ctx );
132}
133
134/* DRBG context free */
135static inline void ecp_drbg_free( ecp_drbg_context *ctx )
136{
137 mbedtls_hmac_drbg_free( ctx );
138}
139
140/* DRBG function */
141static inline int ecp_drbg_random( void *p_rng,
142 unsigned char *output, size_t output_len )
143{
144 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
145}
146
147/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200148static int ecp_drbg_seed( ecp_drbg_context *ctx,
149 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200150{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200151 int ret;
152 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200153 /* The list starts with strong hashes */
154 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
155 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
156
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200157 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
158 secret_bytes, secret_len ) );
159
160 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
161
162cleanup:
163 mbedtls_zeroize( secret_bytes, secret_len );
164
165 return( ret );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200166}
167
168#elif defined(MBEDTLS_CTR_DRBG_C)
169
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200170/* DRBG context type */
171typedef mbedtls_ctr_drbg_context ecp_drbg_context;
172
173/* DRBG context init */
174static inline void ecp_drbg_init( ecp_drbg_context *ctx )
175{
176 mbedtls_ctr_drbg_init( ctx );
177}
178
179/* DRBG context free */
180static inline void ecp_drbg_free( ecp_drbg_context *ctx )
181{
182 mbedtls_ctr_drbg_free( ctx );
183}
184
185/* DRBG function */
186static inline int ecp_drbg_random( void *p_rng,
187 unsigned char *output, size_t output_len )
188{
189 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
190}
191
192/*
193 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
194 * we need to pass an entropy function when seeding. So we use a dummy
195 * function for that, and pass the actual entropy as customisation string.
196 * (During seeding of CTR_DRBG the entropy input and customisation string are
197 * concatenated before being used to update the secret state.)
198 */
199static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
200{
201 (void) ctx;
202 memset( out, 0, len );
203 return( 0 );
204}
205
206/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200207static int ecp_drbg_seed( ecp_drbg_context *ctx,
208 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200209{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200210 int ret;
211 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200212
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200213 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
214 secret_bytes, secret_len ) );
215
216 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
217 secret_bytes, secret_len );
218
219cleanup:
220 mbedtls_zeroize( secret_bytes, secret_len );
221
222 return( ret );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200223}
224
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200225#elif defined(MBEDTLS_SHA512_C) || \
226 defined(MBEDTLS_SHA256_C) || \
227 defined(MBEDTLS_SHA1_C)
228
229/* This will be used in the self-test function */
230#define ECP_ONE_STEP_KDF
231
232/*
233 * We need to expand secret data (the scalar) into a longer stream of bytes.
234 *
235 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
236 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
237 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
238 *
239 * We need a basic hash abstraction layer to use whatever SHA is available.
240 */
241#if defined(MBEDTLS_SHA512_C)
242
243#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
244#define HASH_BLOCK_BYTES ( 512 / 8 )
245
246#elif defined(MBEDTLS_SHA256_C)
247
248#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
249#define HASH_BLOCK_BYTES ( 256 / 8 )
250
251#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
252
253#define HASH_FUNC mbedtls_sha1_ret
254#define HASH_BLOCK_BYTES ( 160 / 8 )
255
256#endif /* SHA512/SHA256/SHA1 abstraction */
257
258/*
259 * State consists of a 32-bit counter plus the secret value.
260 *
261 * We stored them concatenated in a single buffer as that's what will get
262 * passed to the hash function.
263 */
264typedef struct {
265 size_t total_len;
266 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
267} ecp_drbg_context;
268
269static void ecp_drbg_init( ecp_drbg_context *ctx )
270{
271 memset( ctx, 0, sizeof( ecp_drbg_context ) );
272}
273
274static void ecp_drbg_free( ecp_drbg_context *ctx )
275{
276 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
277}
278
279static int ecp_drbg_seed( ecp_drbg_context *ctx,
280 const mbedtls_mpi *secret, size_t secret_len )
281{
282 ctx->total_len = 4 + secret_len;
283 memset( ctx->buf, 0, 4);
284 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
285}
286
287static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
288{
289 ecp_drbg_context *ctx = p_rng;
290 int ret;
291 size_t len_done = 0;
292
293 while( len_done < output_len )
294 {
295 uint8_t tmp[HASH_BLOCK_BYTES];
296 uint8_t use_len;
297
298 /* We don't need to draw more that 255 blocks, so don't bother with
299 * carry propagation and just return an error instead. */
300 ctx->buf[3] += 1;
301 if( ctx->buf[3] == 0 )
302 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
303
304 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
305 if( ret != 0 )
306 return( ret );
307
308 if( output_len - len_done > HASH_BLOCK_BYTES )
309 use_len = HASH_BLOCK_BYTES;
310 else
311 use_len = output_len - len_done;
312
313 memcpy( output + len_done, tmp, use_len );
314 len_done += use_len;
315 }
316
317 return( 0 );
318}
319
320#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200321#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200322#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200323#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
324
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
326 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
327 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
328 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
329 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
330 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
331 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
332 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
333 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
334 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
335 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200336#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100337#endif
338
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200339#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200340#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100341#endif
342
343/*
344 * Curve types: internal for now, might be exposed later
345 */
346typedef enum
347{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200348 ECP_TYPE_NONE = 0,
349 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
350 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100351} ecp_curve_type;
352
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100353/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200354 * List of supported curves:
355 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200356 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200357 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200358 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100359 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100360 * Curves are listed in order: largest curves first, and for a given size,
361 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200362 *
363 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200366{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
368 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200369#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200370#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
371 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100372#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
374 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200375#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
377 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100378#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
380 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200381#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
383 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100384#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
386 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100387#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
389 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200390#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
392 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100393#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
395 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100396#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
398 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100399#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200401};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100402
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200403#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
404 sizeof( ecp_supported_curves[0] )
405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200407
408/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200409 * List of supported curves and associated info
410 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200412{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200413 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200414}
415
416/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100417 * List of supported curves, group ID only
418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100420{
421 static int init_done = 0;
422
423 if( ! init_done )
424 {
425 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100427
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 for( curve_info = mbedtls_ecp_curve_list();
429 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100430 curve_info++ )
431 {
432 ecp_supported_grp_id[i++] = curve_info->grp_id;
433 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100435
436 init_done = 1;
437 }
438
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200439 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100440}
441
442/*
443 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200444 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445const 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 +0200446{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200448
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 for( curve_info = mbedtls_ecp_curve_list();
450 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200451 curve_info++ )
452 {
453 if( curve_info->grp_id == grp_id )
454 return( curve_info );
455 }
456
457 return( NULL );
458}
459
460/*
461 * Get the curve info from the TLS identifier
462 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200464{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200466
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 for( curve_info = mbedtls_ecp_curve_list();
468 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200469 curve_info++ )
470 {
471 if( curve_info->tls_id == tls_id )
472 return( curve_info );
473 }
474
475 return( NULL );
476}
477
478/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100479 * Get the curve info from the name
480 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100482{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 for( curve_info = mbedtls_ecp_curve_list();
486 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100487 curve_info++ )
488 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200489 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100490 return( curve_info );
491 }
492
493 return( NULL );
494}
495
496/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100497 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100498 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100500{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100501 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200502 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100503
504 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200505 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100506 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200507 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100508}
509
510/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100511 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100512 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200513void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100514{
515 if( pt == NULL )
516 return;
517
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_mpi_init( &pt->X );
519 mbedtls_mpi_init( &pt->Y );
520 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100521}
522
523/*
524 * Initialize (the components of) a group
525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100527{
528 if( grp == NULL )
529 return;
530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100532}
533
534/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200535 * Initialize (the components of) a key pair
536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200538{
Paul Bakker66d5d072014-06-17 16:39:18 +0200539 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200540 return;
541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_ecp_group_init( &key->grp );
543 mbedtls_mpi_init( &key->d );
544 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200545}
546
547/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100548 * Unallocate (the components of) a point
549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100551{
552 if( pt == NULL )
553 return;
554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_mpi_free( &( pt->X ) );
556 mbedtls_mpi_free( &( pt->Y ) );
557 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100558}
559
560/*
561 * Unallocate (the components of) a group
562 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100564{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200565 size_t i;
566
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100567 if( grp == NULL )
568 return;
569
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100570 if( grp->h != 1 )
571 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 mbedtls_mpi_free( &grp->P );
573 mbedtls_mpi_free( &grp->A );
574 mbedtls_mpi_free( &grp->B );
575 mbedtls_ecp_point_free( &grp->G );
576 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100577 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200578
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200579 if( grp->T != NULL )
580 {
581 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 mbedtls_ecp_point_free( &grp->T[i] );
583 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200584 }
585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100587}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100588
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100589/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200590 * Unallocate (the components of) a key pair
591 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200593{
Paul Bakker66d5d072014-06-17 16:39:18 +0200594 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200595 return;
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 mbedtls_ecp_group_free( &key->grp );
598 mbedtls_mpi_free( &key->d );
599 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200600}
601
602/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200603 * Copy the contents of a point
604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200606{
607 int ret;
608
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
610 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
611 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200612
613cleanup:
614 return( ret );
615}
616
617/*
618 * Copy the contents of a group object
619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200621{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200622 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200623}
624
625/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100626 * Set point to zero
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100629{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100630 int ret;
631
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
633 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
634 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100635
636cleanup:
637 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100638}
639
640/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100641 * Tell if a point is zero
642 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200643int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100644{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100646}
647
648/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700649 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200650 */
651int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
652 const mbedtls_ecp_point *Q )
653{
654 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
655 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
656 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
657 {
658 return( 0 );
659 }
660
661 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
662}
663
664/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100665 * Import a non-zero point from ASCII strings
666 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100668 const char *x, const char *y )
669{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100670 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100671
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200672 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
673 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
674 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100675
676cleanup:
677 return( ret );
678}
679
680/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100681 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100684 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100685 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100686{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200687 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100688 size_t plen;
689
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
691 format != MBEDTLS_ECP_PF_COMPRESSED )
692 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100693
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100694 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100695 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100696 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100698 {
699 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100701
702 buf[0] = 0x00;
703 *olen = 1;
704
705 return( 0 );
706 }
707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100711 {
712 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100713
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100714 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100716
717 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
719 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100720 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100722 {
723 *olen = plen + 1;
724
725 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
729 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100730 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100731
732cleanup:
733 return( ret );
734}
735
736/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100737 * Import a point from unsigned binary data (SEC1 2.3.4)
738 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100740 const unsigned char *buf, size_t ilen )
741{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100742 int ret;
743 size_t plen;
744
Paul Bakker82788fb2014-10-20 13:59:19 +0200745 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200747
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100748 if( buf[0] == 0x00 )
749 {
750 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100752 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100754 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100757
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100758 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100760
761 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200762 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100763
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
765 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
766 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100767
768cleanup:
769 return( ret );
770}
771
772/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100773 * Import a point from a TLS ECPoint record (RFC 4492)
774 * struct {
775 * opaque point <1..2^8-1>;
776 * } ECPoint;
777 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200778int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100779 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100780{
781 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100782 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100783
784 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200785 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100786 */
787 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200788 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100789
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100790 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100791 if( data_len < 1 || data_len > buf_len - 1 )
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 /*
795 * Save buffer start for read_binary and update buf
796 */
797 buf_start = *buf;
798 *buf += data_len;
799
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200800 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100801}
802
803/*
804 * Export a point as a TLS ECPoint record (RFC 4492)
805 * struct {
806 * opaque point <1..2^8-1>;
807 * } ECPoint;
808 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100810 int format, size_t *olen,
811 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100812{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100813 int ret;
814
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100815 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100816 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100817 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100818 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100820
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100822 olen, buf + 1, blen - 1) ) != 0 )
823 return( ret );
824
825 /*
826 * write length to the first byte and update total length
827 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200828 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100829 ++*olen;
830
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200831 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100832}
833
834/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100835 * Set a group from an ECParameters record (RFC 4492)
836 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837int 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 +0100838{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200839 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200840 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100841
842 /*
843 * We expect at least three bytes (see below)
844 */
845 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100847
848 /*
849 * First byte is curve_type; only named_curve is handled
850 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
852 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100853
854 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100855 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100856 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200857 tls_id = *(*buf)++;
858 tls_id <<= 8;
859 tls_id |= *(*buf)++;
860
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
862 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200863
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200864 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100865}
866
867/*
868 * Write the ECParameters record corresponding to a group (RFC 4492)
869 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100871 unsigned char *buf, size_t blen )
872{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200873 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200874
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
876 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200877
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100878 /*
879 * We are going to write 3 bytes (see below)
880 */
881 *olen = 3;
882 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100884
885 /*
886 * First byte is curve_type, always named_curve
887 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100889
890 /*
891 * Next two bytes are the namedcurve value
892 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200893 buf[0] = curve_info->tls_id >> 8;
894 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100895
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200896 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100897}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100898
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200899/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200900 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
901 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200902 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 * 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 +0200904 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200906{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200907 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200908
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200909 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200911
912 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200913 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200914 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200915 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200917 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200918
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200920
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200921 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200922 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
923 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200924
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200925 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200926 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200928
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200929cleanup:
930 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200931}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200932
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100933/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100934 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100935 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100936 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200937 * 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 +0100938 * bring the result back to this range.
939 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100940 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100941 */
942
943/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 * 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 +0100945 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100947#define INC_MUL_COUNT mul_count++;
948#else
949#define INC_MUL_COUNT
950#endif
951
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100953 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100954
955/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200957 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100958 */
959#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
961 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100962
963/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200964 * 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 +0200965 * We known P, N and the result are positive, so sub_abs is correct, and
966 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100967 */
968#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
970 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100971
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200972#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100973/*
974 * For curves in short Weierstrass form, we do all the internal operations in
975 * Jacobian coordinates.
976 *
977 * For multiplication, we'll use a comb method with coutermeasueres against
978 * SPA, hence timing attacks.
979 */
980
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100981/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100982 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100983 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100984 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100986{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100987 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200988 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100991 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100992
Janos Follathb0697532016-08-18 12:38:46 +0100993#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000994 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100995 {
Janos Follathc44ab972016-11-18 16:38:23 +0000996 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +0100997 }
Janos Follath372697b2016-10-28 16:53:11 +0100998#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200999 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001000
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001001 /*
1002 * X = X / Z^2 mod p
1003 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1005 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1006 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 +01001007
1008 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001009 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001010 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1012 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 +01001013
1014 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001015 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001018
1019cleanup:
1020
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001021 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001022
1023 return( ret );
1024}
1025
1026/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001027 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001028 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001029 * (See for example Cohen's "A Course in Computational Algebraic Number
1030 * Theory", Algorithm 10.3.4.)
1031 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001032 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001033 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001034 *
1035 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001036 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001037static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1038 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001039{
1040 int ret;
1041 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001043
1044 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001045 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001046
Janos Follathb0697532016-08-18 12:38:46 +01001047#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001048 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001049 {
Janos Follathc44ab972016-11-18 16:38:23 +00001050 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001051 }
1052#endif
1053
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001054 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001055 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001056
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001057 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001058
1059 /*
1060 * c[i] = Z_0 * ... * Z_i
1061 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001062 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001063 for( i = 1; i < t_len; i++ )
1064 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001065 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001066 MOD_MUL( c[i] );
1067 }
1068
1069 /*
1070 * u = 1 / (Z_0 * ... * Z_n) mod P
1071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001072 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001073
1074 for( i = t_len - 1; ; i-- )
1075 {
1076 /*
1077 * Zi = 1 / Z_i mod p
1078 * u = 1 / (Z_0 * ... * Z_i) mod P
1079 */
1080 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001081 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001082 }
1083 else
1084 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1086 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001087 }
1088
1089 /*
1090 * proceed as in normalize()
1091 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001092 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1093 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1094 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1095 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 +01001096
1097 /*
1098 * Post-precessing: reclaim some memory by shrinking coordinates
1099 * - not storing Z (always 1)
1100 * - shrinking other coordinates, but still keeping the same number of
1101 * limbs as P, as otherwise it will too likely be regrown too fast.
1102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001103 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1104 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1105 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001106
1107 if( i == 0 )
1108 break;
1109 }
1110
1111cleanup:
1112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001113 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001114 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_free( &c[i] );
1116 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001117
1118 return( ret );
1119}
1120
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001121/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001122 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1123 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1124 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001125static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1126 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001127 unsigned char inv )
1128{
1129 int ret;
1130 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001131 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001132
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001134
1135 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001136 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1137 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1138 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001139
1140cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001141 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001142
1143 return( ret );
1144}
1145
1146/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001147 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001148 *
Peter Dettmance661b22015-02-07 14:43:51 +07001149 * 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 +01001150 *
Peter Dettmance661b22015-02-07 14:43:51 +07001151 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1152 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1153 *
1154 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1155 *
1156 * Cost: 1D := 3M + 4S (A == 0)
1157 * 4M + 4S (A == -3)
1158 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1161 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001162{
1163 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001164 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001165
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001166#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001167 dbl_count++;
1168#endif
1169
Janos Follathb0697532016-08-18 12:38:46 +01001170#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001171 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001172 {
Janos Follathc44ab972016-11-18 16:38:23 +00001173 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001174 }
Janos Follath372697b2016-10-28 16:53:11 +01001175#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001176
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001177 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 +01001178
1179 /* Special case for A = -3 */
1180 if( grp->A.p == NULL )
1181 {
Peter Dettmance661b22015-02-07 14:43:51 +07001182 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001183 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1184 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1185 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1186 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1187 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001188 }
1189 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001190 {
Peter Dettmance661b22015-02-07 14:43:51 +07001191 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001192 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1193 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001194
1195 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001196 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001197 {
1198 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001199 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1200 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1201 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1202 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001203 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001204 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001205
Peter Dettmance661b22015-02-07 14:43:51 +07001206 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001207 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1208 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1209 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001211
Peter Dettmance661b22015-02-07 14:43:51 +07001212 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001213 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001215
1216 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001217 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1218 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1219 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001220
1221 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001222 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1223 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1224 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001225
1226 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001227 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1228 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001229
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1231 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1232 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001233
1234cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001235 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 +02001236
1237 return( ret );
1238}
1239
1240/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001241 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001242 *
1243 * The coordinates of Q must be normalized (= affine),
1244 * but those of P don't need to. R is not normalized.
1245 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001246 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001247 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001248 * - at each step, P, Q and R are multiples of the base point, the factor
1249 * being less than its order, so none of them is zero;
1250 * - Q is an odd multiple of the base point, P an even multiple,
1251 * due to the choice of precomputed points in the modified comb method.
1252 * So branches for these cases do not leak secret information.
1253 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001254 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1255 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001256 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001257 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001258static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1259 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001260{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001261 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001262 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001265 add_count++;
1266#endif
1267
Janos Follathb0697532016-08-18 12:38:46 +01001268#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001269 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001270 {
Janos Follathc44ab972016-11-18 16:38:23 +00001271 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001272 }
Janos Follath372697b2016-10-28 16:53:11 +01001273#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001274
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001275 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001276 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001278 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1279 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001280
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001281 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1282 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001283
1284 /*
1285 * Make sure Q coordinates are normalized
1286 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001287 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1288 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001289
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001290 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1291 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1294 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1295 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1296 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1297 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1298 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001299
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001300 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001301 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001302 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001304 {
1305 ret = ecp_double_jac( grp, R, P );
1306 goto cleanup;
1307 }
1308 else
1309 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001310 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001311 goto cleanup;
1312 }
1313 }
1314
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001315 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1316 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1317 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1318 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1319 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1320 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1321 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1325 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1326 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1330 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001331
1332cleanup:
1333
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1335 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001336
1337 return( ret );
1338}
1339
1340/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001341 * Randomize jacobian coordinates:
1342 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001343 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001344 *
1345 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001346 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001348 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1349{
1350 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001351 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001352 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001353 int count = 0;
1354
Janos Follathb0697532016-08-18 12:38:46 +01001355#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001356 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001357 {
Janos Follathc44ab972016-11-18 16:38:23 +00001358 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001359 }
Janos Follath372697b2016-10-28 16:53:11 +01001360#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001361
1362 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001363 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001364
1365 /* Generate l such that 1 < l < p */
1366 do
1367 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001370 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1371 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001372
1373 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001374 {
1375 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1376 goto cleanup;
1377 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001378 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001380
1381 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001382 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 +02001383
1384 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001385 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1386 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 +02001387
1388 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1390 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 +02001391
1392cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001393 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001394
1395 return( ret );
1396}
1397
1398/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001399 * Check and define parameters used by the comb method (see below for details)
1400 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001401#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1402#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001403#endif
1404
1405/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001407
1408/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001409#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001410
1411/*
1412 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001413 *
1414 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001415 * modified version that provides resistance to SPA by avoiding zero
1416 * digits in the representation as in [3]. We modify the method further by
1417 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001418 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001419 *
1420 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1421 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1422 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001423 *
1424 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001425 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001426 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001427 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001428 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1429 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001430 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001431static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001432 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001433{
1434 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001435 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001436
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001437 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001438
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001439 /* First get the classical comb values (except for x_d = 0) */
1440 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001441 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001442 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001443
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001444 /* Now make sure x_1 .. x_d are odd */
1445 c = 0;
1446 for( i = 1; i <= d; i++ )
1447 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001448 /* Add carry and update it */
1449 cc = x[i] & c;
1450 x[i] = x[i] ^ c;
1451 c = cc;
1452
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001453 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001454 adjust = 1 - ( x[i] & 0x01 );
1455 c |= x[i] & ( x[i-1] * adjust );
1456 x[i] = x[i] ^ ( x[i-1] * adjust );
1457 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001458 }
1459}
1460
1461/*
1462 * Precompute points for the comb method
1463 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001464 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1465 * 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 +01001466 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001467 * T must be able to hold 2^{w - 1} elements
1468 *
1469 * 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 +01001470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001471static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1472 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001473 unsigned char w, size_t d )
1474{
1475 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001476 unsigned char i, k;
1477 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001478 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001479
1480 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001481 * Set T[0] = P and
1482 * 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 +01001483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001485
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001486 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001487 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001488 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001489 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001490 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001491 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001493
1494 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001495 }
1496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001498
1499 /*
1500 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001501 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001502 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001503 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001504 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001505 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001506 j = i;
1507 while( j-- )
1508 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001509 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001510 TT[k++] = &T[i + j];
1511 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001512 }
1513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001514 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001515
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001516cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001517
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001518 return( ret );
1519}
1520
1521/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001522 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001523 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001524static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1525 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001526 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001527{
1528 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001529 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001530
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001531 /* Ignore the "sign" bit and scale down */
1532 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001533
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001534 /* Read the whole table to thwart cache-based timing attacks */
1535 for( j = 0; j < t_len; j++ )
1536 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1538 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001539 }
1540
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001541 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001542 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001543
1544cleanup:
1545 return( ret );
1546}
1547
1548/*
1549 * Core multiplication algorithm for the (modified) comb method.
1550 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001551 *
1552 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001553 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001554static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1555 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001556 const unsigned char x[], size_t d,
1557 int (*f_rng)(void *, unsigned char *, size_t),
1558 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001559{
1560 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001561 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001562 size_t i;
1563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001564 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001565
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001566 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001567 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001568 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1569 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001570#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001571 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001572#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001573 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001574
1575 while( i-- != 0 )
1576 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1578 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1579 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001580 }
1581
1582cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001583
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001584 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001585
1586 return( ret );
1587}
1588
1589/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001590 * Multiplication using the comb method,
1591 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001592 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001593static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1594 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001595 int (*f_rng)(void *, unsigned char *, size_t),
1596 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001597{
1598 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001599 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1600 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001601 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001602 mbedtls_ecp_point *T;
1603 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001604
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001605 mbedtls_mpi_init( &M );
1606 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001607
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001608 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001609 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1610 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001611
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001612 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001613 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001614 * 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 +01001615 * (see costs of the various parts, with 1S = 1M)
1616 */
1617 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001618
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001619 /*
1620 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001621 * Just adding one avoids upping the cost of the first mul too much,
1622 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001623 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001624#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1625 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1626 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001627 if( p_eq_g )
1628 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001629#else
1630 p_eq_g = 0;
1631#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001632
1633 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001634 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001635 * (The last test is useful only for very small curves in the test suite.)
1636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1638 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001639 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001640 w = 2;
1641
1642 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001643 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001644 d = ( grp->nbits + w - 1 ) / w;
1645
1646 /*
1647 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001648 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001649 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001650 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001651
1652 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001653 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001654 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001655 if( T == NULL )
1656 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001657 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001658 goto cleanup;
1659 }
1660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001661 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001662
1663 if( p_eq_g )
1664 {
1665 grp->T = T;
1666 grp->T_size = pre_len;
1667 }
1668 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001669
1670 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001671 * Make sure M is odd (M = m or M = N - m, since N is odd)
1672 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1675 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1676 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001678
1679 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001680 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001681 */
1682 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001683 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 +01001684
1685 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001686 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001687 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001689
1690 /*
1691 * Knowledge of the jacobian coordinates may leak the last few bits of the
1692 * scalar [1], and since our MPI implementation isn't constant-flow,
1693 * inversion (used for coordinate normalization) may leak the full value
1694 * of its input via side-channels [2].
1695 *
1696 * [1] https://eprint.iacr.org/2003/191
1697 * [2] https://eprint.iacr.org/2020/055
1698 *
1699 * Avoid the leak by randomizing coordinates before we normalize them.
1700 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001701#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001702 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001703#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001704 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001705 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001706
1707cleanup:
1708
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001709 /* There are two cases where T is not stored in grp:
1710 * - P != G
1711 * - An intermediate operation failed before setting grp->T
1712 * In either case, T must be freed.
1713 */
1714 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001715 {
1716 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001717 mbedtls_ecp_point_free( &T[i] );
1718 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001719 }
1720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001721 mbedtls_mpi_free( &M );
1722 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001723
1724 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001725 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001726
1727 return( ret );
1728}
1729
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001730#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001731
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001732#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001733/*
1734 * For Montgomery curves, we do all the internal arithmetic in projective
1735 * coordinates. Import/export of points uses only the x coordinates, which is
1736 * internaly represented as X / Z.
1737 *
1738 * For scalar multiplication, we'll use a Montgomery ladder.
1739 */
1740
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001741/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001742 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1743 * Cost: 1M + 1I
1744 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001745static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001746{
1747 int ret;
1748
Janos Follathb0697532016-08-18 12:38:46 +01001749#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001750 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001751 {
Janos Follathc44ab972016-11-18 16:38:23 +00001752 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001753 }
Janos Follath372697b2016-10-28 16:53:11 +01001754#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001756 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1757 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1758 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001759
1760cleanup:
1761 return( ret );
1762}
1763
1764/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001765 * Randomize projective x/z coordinates:
1766 * (X, Z) -> (l X, l Z) for random l
1767 * This is sort of the reverse operation of ecp_normalize_mxz().
1768 *
1769 * This countermeasure was first suggested in [2].
1770 * Cost: 2M
1771 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001772static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001773 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1774{
1775 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001777 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001778 int count = 0;
1779
Janos Follathb0697532016-08-18 12:38:46 +01001780#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001781 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001782 {
Janos Follathc44ab972016-11-18 16:38:23 +00001783 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001784 }
Janos Follath372697b2016-10-28 16:53:11 +01001785#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001786
1787 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001788 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001789
1790 /* Generate l such that 1 < l < p */
1791 do
1792 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001793 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001794
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001795 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1796 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001797
1798 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001799 {
1800 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1801 goto cleanup;
1802 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001803 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001804 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001805
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1807 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 +01001808
1809cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001810 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001811
1812 return( ret );
1813}
1814
1815/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001816 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1817 * for Montgomery curves in x/z coordinates.
1818 *
1819 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1820 * with
1821 * d = X1
1822 * P = (X2, Z2)
1823 * Q = (X3, Z3)
1824 * R = (X4, Z4)
1825 * S = (X5, Z5)
1826 * and eliminating temporary variables tO, ..., t4.
1827 *
1828 * Cost: 5M + 4S
1829 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001830static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1831 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1832 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1833 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001834{
1835 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001836 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001837
Janos Follathb0697532016-08-18 12:38:46 +01001838#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001839 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001840 {
Janos Follathc44ab972016-11-18 16:38:23 +00001841 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001842 }
Janos Follath372697b2016-10-28 16:53:11 +01001843#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001844
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001845 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1846 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1847 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001848
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1850 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1851 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1852 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1853 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1858 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1866 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 +01001867
1868cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001869 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1870 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1871 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001872
1873 return( ret );
1874}
1875
1876/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001877 * Multiplication with Montgomery ladder in x/z coordinates,
1878 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001879 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001880static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1881 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001882 int (*f_rng)(void *, unsigned char *, size_t),
1883 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001884{
1885 int ret;
1886 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001887 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001888 mbedtls_ecp_point RP;
1889 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001890
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001891 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001892
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001893 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001894 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1895 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001896
1897 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1899 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1900 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001901
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001902 /* RP.X might be sligtly larger than P, so reduce it */
1903 MOD_ADD( RP.X );
1904
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001905 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001906#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001907 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001908#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001909 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001910
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001911 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001912 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001913 while( i-- > 0 )
1914 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001915 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001916 /*
1917 * if (b) R = 2R + P else R = 2R,
1918 * which is:
1919 * if (b) double_add( RP, R, RP, R )
1920 * else double_add( R, RP, R, RP )
1921 * but using safe conditional swaps to avoid leaks
1922 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001923 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1924 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1925 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1926 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1927 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001928 }
1929
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001930 /*
1931 * Knowledge of the projective coordinates may leak the last few bits of the
1932 * scalar [1], and since our MPI implementation isn't constant-flow,
1933 * inversion (used for coordinate normalization) may leak the full value
1934 * of its input via side-channels [2].
1935 *
1936 * [1] https://eprint.iacr.org/2003/191
1937 * [2] https://eprint.iacr.org/2020/055
1938 *
1939 * Avoid the leak by randomizing coordinates before we normalize them.
1940 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001941#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001942 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001943#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001944 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1945
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001946 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001947
1948cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001950
1951 return( ret );
1952}
1953
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001954#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001955
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001956/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001957 * Multiplication R = m * P
1958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1960 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001961 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1962{
Janos Follathb0697532016-08-18 12:38:46 +01001963 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001964#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1965 char is_grp_capable = 0;
1966#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001967#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1968 ecp_drbg_context drbg_ctx;
1969
1970 ecp_drbg_init( &drbg_ctx );
1971#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001972
1973 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001974 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1975 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001976
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001977 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1978 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001979 return( ret );
1980
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001981#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1982 if( f_rng == NULL )
1983 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02001984 const size_t m_len = ( grp->nbits + 7 ) / 8;
1985 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001986 f_rng = &ecp_drbg_random;
1987 p_rng = &drbg_ctx;
1988 }
1989#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
1990
Janos Follathc44ab972016-11-18 16:38:23 +00001991#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001992 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001993 {
Janos Follathc44ab972016-11-18 16:38:23 +00001994 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01001995 }
Janos Follathc44ab972016-11-18 16:38:23 +00001996#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001997
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001998#if defined(ECP_MONTGOMERY)
1999 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002000 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002001#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002002#if defined(ECP_SHORTWEIERSTRASS)
2003 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002004 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002005#endif
Janos Follathb0697532016-08-18 12:38:46 +01002006
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002007#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2008cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002009#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002010#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002011 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002012 {
Janos Follathc44ab972016-11-18 16:38:23 +00002013 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002014 }
Janos Follathc44ab972016-11-18 16:38:23 +00002015#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002016
2017#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2018 ecp_drbg_free( &drbg_ctx );
2019#endif
2020
Janos Follathb0697532016-08-18 12:38:46 +01002021 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002022}
2023
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002024#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002025/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002026 * Check that an affine point is valid as a public key,
2027 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002028 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002029static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002030{
2031 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002032 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002033
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002034 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002035 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2036 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2037 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2038 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2039 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002041 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002042
2043 /*
2044 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002045 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002046 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002047 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2048 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002049
2050 /* Special case for A = -3 */
2051 if( grp->A.p == NULL )
2052 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002053 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002054 }
2055 else
2056 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002057 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002058 }
2059
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2064 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002065
2066cleanup:
2067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002068 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002069
2070 return( ret );
2071}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002072#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002073
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002074/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002075 * R = m * P with shortcuts for m == 1 and m == -1
2076 * NOT constant-time - ONLY for short Weierstrass!
2077 */
2078static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2079 mbedtls_ecp_point *R,
2080 const mbedtls_mpi *m,
2081 const mbedtls_ecp_point *P )
2082{
2083 int ret;
2084
2085 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2086 {
2087 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2088 }
2089 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2090 {
2091 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2092 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2093 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2094 }
2095 else
2096 {
2097 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2098 }
2099
2100cleanup:
2101 return( ret );
2102}
2103
2104/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002105 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002106 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002107 */
2108int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2109 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2110 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2111{
2112 int ret;
2113 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002114#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2115 char is_grp_capable = 0;
2116#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002117
2118 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2119 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2120
2121 mbedtls_ecp_point_init( &mP );
2122
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002123 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2124 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002125
Janos Follathc44ab972016-11-18 16:38:23 +00002126#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002127 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002128 {
Janos Follathc44ab972016-11-18 16:38:23 +00002129 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002130 }
Janos Follath430d3372016-11-03 14:25:37 +00002131
Janos Follathc44ab972016-11-18 16:38:23 +00002132#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002133 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2134 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2135
2136cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002137
Janos Follathc44ab972016-11-18 16:38:23 +00002138#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2139 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002140 {
Janos Follathc44ab972016-11-18 16:38:23 +00002141 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002142 }
Janos Follathb0697532016-08-18 12:38:46 +01002143
Janos Follathc44ab972016-11-18 16:38:23 +00002144#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002145 mbedtls_ecp_point_free( &mP );
2146
2147 return( ret );
2148}
2149
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002150
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002151#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002152/*
2153 * Check validity of a public key for Montgomery curves with x-only schemes
2154 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002155static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002156{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002157 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002158 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2159 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002160
2161 return( 0 );
2162}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002163#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002164
2165/*
2166 * Check that a point is valid as a public key
2167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002169{
2170 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2172 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002173
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002174#if defined(ECP_MONTGOMERY)
2175 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002176 return( ecp_check_pubkey_mx( grp, pt ) );
2177#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002178#if defined(ECP_SHORTWEIERSTRASS)
2179 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002180 return( ecp_check_pubkey_sw( grp, pt ) );
2181#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002182 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002183}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002184
2185/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002186 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002189{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002190#if defined(ECP_MONTGOMERY)
2191 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002192 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002193 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002194 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2195 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2196 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002197 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002199 else
2200 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002201 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002202#endif /* ECP_MONTGOMERY */
2203#if defined(ECP_SHORTWEIERSTRASS)
2204 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002205 {
2206 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2208 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2209 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002210 else
2211 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002212 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002213#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002215 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002216}
2217
2218/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002219 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002220 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002221int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2222 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002223 int (*f_rng)(void *, unsigned char *, size_t),
2224 void *p_rng )
2225{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002226 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002227 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002228
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002229#if defined(ECP_MONTGOMERY)
2230 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002231 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002232 /* [M225] page 5 */
2233 size_t b;
2234
Janos Follath98e28a72016-05-31 14:03:54 +01002235 do {
2236 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2237 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002238
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002239 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002240 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002241 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002242 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002243 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002245
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002246 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2248 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002250 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002251#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002252
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002253#if defined(ECP_SHORTWEIERSTRASS)
2254 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002255 {
2256 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002257 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002258 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002259
2260 /*
2261 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2262 * - use the same byte ordering;
2263 * - keep the leftmost nbits bits of the generated octet string;
2264 * - try until result is in the desired range.
2265 * This also avoids any biais, which is especially important for ECDSA.
2266 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002267 do
2268 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002269 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002270 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002271
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002272 /*
2273 * Each try has at worst a probability 1/2 of failing (the msb has
2274 * a probability 1/2 of being 0, and then the result will be < N),
2275 * so after 30 tries failure probability is a most 2**(-30).
2276 *
2277 * For most curves, 1 try is enough with overwhelming probability,
2278 * since N starts with a lot of 1s in binary, but some curves
2279 * such as secp224k1 are actually very close to the worst case.
2280 */
2281 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002282 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002283
Janos Follathc3b376e2019-10-11 14:21:53 +01002284 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002285 if( ret != 0 )
2286 {
2287 goto cleanup;
2288 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002289 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002290 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002291 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002292#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002293
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002294cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002295 return( ret );
2296}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002297
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002298/*
2299 * Generate a keypair with configurable base point
2300 */
2301int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2302 const mbedtls_ecp_point *G,
2303 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2304 int (*f_rng)(void *, unsigned char *, size_t),
2305 void *p_rng )
2306{
2307 int ret;
2308
2309 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2310 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2311
2312cleanup:
2313 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002314}
2315
2316/*
2317 * Generate key pair, wrapper for conventional base point
2318 */
2319int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2320 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2321 int (*f_rng)(void *, unsigned char *, size_t),
2322 void *p_rng )
2323{
2324 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002325}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002326
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002327/*
2328 * Generate a keypair, prettier wrapper
2329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002331 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2332{
2333 int ret;
2334
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002335 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002336 return( ret );
2337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002339}
2340
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002341/*
2342 * Check a public-private key pair
2343 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002344int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002345{
2346 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 mbedtls_ecp_point Q;
2348 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002349
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002350 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002351 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2353 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2354 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002355 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002356 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002357 }
2358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 mbedtls_ecp_point_init( &Q );
2360 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002361
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002362 /* mbedtls_ecp_mul() needs a non-const group... */
2363 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002364
2365 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002367
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2369 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2370 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002371 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002373 goto cleanup;
2374 }
2375
2376cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002377 mbedtls_ecp_point_free( &Q );
2378 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002379
2380 return( ret );
2381}
2382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002383#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002384
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002385#if defined(ECP_ONE_STEP_KDF)
2386/*
2387 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2388 * but unofficial ones can be found at:
2389 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2390 *
2391 * We only use the ones with empty fixedInfo, and for brevity's sake, only
2392 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
2393 * exactly one block, and with SHA-512 less than one block).
2394 */
2395#if defined(MBEDTLS_SHA512_C)
2396
2397static const uint8_t test_kdf_z[16] = {
2398 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
2399 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
2400};
2401static const uint8_t test_kdf_out[32] = {
2402 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
2403 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
2404 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
2405 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
2406};
2407
2408#elif defined(MBEDTLS_SHA256_C)
2409
2410static const uint8_t test_kdf_z[16] = {
2411 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
2412 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
2413};
2414static const uint8_t test_kdf_out[32] = {
2415 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
2416 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
2417 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
2418 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
2419};
2420
2421#elif defined(MBEDTLS_SHA1_C)
2422
2423static const uint8_t test_kdf_z[16] = {
2424 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
2425 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
2426};
2427static const uint8_t test_kdf_out[32] = {
2428 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
2429 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
2430 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
2431 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
2432};
2433
2434#else
2435#error "Need at least one of SHA-512, SHA-256 or SHA-1"
2436#endif
2437
2438static int ecp_kdf_self_test( void )
2439{
2440 int ret;
2441 ecp_drbg_context kdf_ctx;
2442 mbedtls_mpi scalar;
2443 uint8_t out[sizeof( test_kdf_out )];
2444
2445 ecp_drbg_init( &kdf_ctx );
2446 mbedtls_mpi_init( &scalar );
2447 memset( out, 0, sizeof( out ) );
2448
2449 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2450 test_kdf_z, sizeof( test_kdf_z ) ) );
2451
2452 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2453 &scalar, sizeof( test_kdf_z ) ) );
2454
2455 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2456
2457 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2458 ret = -1;
2459
2460cleanup:
2461 ecp_drbg_free( &kdf_ctx );
2462 mbedtls_mpi_free( &scalar );
2463
2464 return( ret );
2465}
2466#endif /* ECP_ONE_STEP_KDF */
2467
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002468/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002469 * Checkup routine
2470 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002471int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002472{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002473 int ret;
2474 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002475 mbedtls_ecp_group grp;
2476 mbedtls_ecp_point R, P;
2477 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002478 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002479 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002480 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002481 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002482 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002483 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002484 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002485 "400000000000000000000000000000000000000000000000", /* one and zeros */
2486 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2487 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002488 };
2489
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002490 mbedtls_ecp_group_init( &grp );
2491 mbedtls_ecp_point_init( &R );
2492 mbedtls_ecp_point_init( &P );
2493 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002494
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002495 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002496#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002497 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002498#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002499 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002500#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002501
2502 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002504
2505 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002506 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2507 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002508
2509 add_count = 0;
2510 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002511 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002512 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2513 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002514
2515 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2516 {
2517 add_c_prev = add_count;
2518 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002519 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002520 add_count = 0;
2521 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002522 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002524 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2525 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002526
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002527 if( add_count != add_c_prev ||
2528 dbl_count != dbl_c_prev ||
2529 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002530 {
2531 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002533
2534 ret = 1;
2535 goto cleanup;
2536 }
2537 }
2538
2539 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002540 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002541
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002542 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002543 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002544 /* We computed P = 2G last time, use it */
2545
2546 add_count = 0;
2547 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002548 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002549 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2550 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002551
2552 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2553 {
2554 add_c_prev = add_count;
2555 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002556 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002557 add_count = 0;
2558 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002559 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002560
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002561 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2562 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002563
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002564 if( add_count != add_c_prev ||
2565 dbl_count != dbl_c_prev ||
2566 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002567 {
2568 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002569 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002570
2571 ret = 1;
2572 goto cleanup;
2573 }
2574 }
2575
2576 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002577 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002578
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002579#if defined(ECP_ONE_STEP_KDF)
2580 if( verbose != 0 )
2581 mbedtls_printf( " ECP test #3 (internal KDF): " );
2582
2583 ret = ecp_kdf_self_test();
2584 if( ret != 0 )
2585 {
2586 if( verbose != 0 )
2587 mbedtls_printf( "failed\n" );
2588
2589 ret = 1;
2590 goto cleanup;
2591 }
2592
2593 if( verbose != 0 )
2594 mbedtls_printf( "passed\n" );
2595#endif /* ECP_ONE_STEP_KDF */
2596
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002597cleanup:
2598
2599 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002601
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 mbedtls_ecp_group_free( &grp );
2603 mbedtls_ecp_point_free( &R );
2604 mbedtls_ecp_point_free( &P );
2605 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002606
2607 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002608 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002609
2610 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002611}
2612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002614
Janos Follathb0697532016-08-18 12:38:46 +01002615#endif /* !MBEDTLS_ECP_ALT */
2616
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002617#endif /* MBEDTLS_ECP_C */