blob: e537dbb49ec3d5c02ed7b56d75483915d6e5258b [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;
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200292 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200293
294 while( len_done < output_len )
295 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200296 uint8_t use_len;
297
Manuel Pégourié-Gonnard97972882020-06-17 12:57:33 +0200298 /* This function is only called for coordinate randomisation, which
299 * happens only twice in a scalar multiplication. Each time needs a
300 * random value in the range [2, p-1], and gets it by drawing len(p)
301 * bytes from this function, and retrying up to 10 times if unlucky.
302 *
303 * So for the largest curve, each scalar multiplication draws at most
304 * 2 * 66 bytes. The minimum block size is 20 bytes (with SHA-1), so
305 * that means at most 66 blocks.
306 *
307 * Since we don't need to draw more that 255 blocks, don't bother
308 * with carry propagation and just return an error instead. We can
309 * change that it we even need to draw more blinding values.
310 */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200311 ctx->buf[3] += 1;
312 if( ctx->buf[3] == 0 )
313 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
314
315 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
316 if( ret != 0 )
317 return( ret );
318
319 if( output_len - len_done > HASH_BLOCK_BYTES )
320 use_len = HASH_BLOCK_BYTES;
321 else
322 use_len = output_len - len_done;
323
324 memcpy( output + len_done, tmp, use_len );
325 len_done += use_len;
326 }
327
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200328 mbedtls_zeroize( tmp, sizeof( tmp ) );
329
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200330 return( 0 );
331}
332
333#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200334#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200335#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200336#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
337
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
339 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
340 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
341 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
342 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
343 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
344 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
345 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
346 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
347 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
348 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200349#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100350#endif
351
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200352#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200353#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100354#endif
355
356/*
357 * Curve types: internal for now, might be exposed later
358 */
359typedef enum
360{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200361 ECP_TYPE_NONE = 0,
362 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
363 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100364} ecp_curve_type;
365
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100366/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200367 * List of supported curves:
368 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200369 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200370 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200371 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100372 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100373 * Curves are listed in order: largest curves first, and for a given size,
374 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200375 *
376 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200377 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200379{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
381 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200382#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
384 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100385#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
387 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200388#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
390 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100391#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
393 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200394#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
396 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100397#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
399 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100400#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
402 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200403#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
405 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100406#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
408 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100409#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
411 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100412#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200414};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100415
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200416#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
417 sizeof( ecp_supported_curves[0] )
418
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200420
421/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200422 * List of supported curves and associated info
423 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200425{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200426 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200427}
428
429/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100430 * List of supported curves, group ID only
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100433{
434 static int init_done = 0;
435
436 if( ! init_done )
437 {
438 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 for( curve_info = mbedtls_ecp_curve_list();
442 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100443 curve_info++ )
444 {
445 ecp_supported_grp_id[i++] = curve_info->grp_id;
446 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100448
449 init_done = 1;
450 }
451
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200452 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100453}
454
455/*
456 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200457 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458const 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 +0200459{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 for( curve_info = mbedtls_ecp_curve_list();
463 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200464 curve_info++ )
465 {
466 if( curve_info->grp_id == grp_id )
467 return( curve_info );
468 }
469
470 return( NULL );
471}
472
473/*
474 * Get the curve info from the TLS identifier
475 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200477{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 for( curve_info = mbedtls_ecp_curve_list();
481 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200482 curve_info++ )
483 {
484 if( curve_info->tls_id == tls_id )
485 return( curve_info );
486 }
487
488 return( NULL );
489}
490
491/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100492 * Get the curve info from the name
493 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100495{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498 for( curve_info = mbedtls_ecp_curve_list();
499 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100500 curve_info++ )
501 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200502 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100503 return( curve_info );
504 }
505
506 return( NULL );
507}
508
509/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100510 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100513{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100514 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200515 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100516
517 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200518 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100519 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200520 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100521}
522
523/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100524 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100527{
528 if( pt == NULL )
529 return;
530
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200531 mbedtls_mpi_init( &pt->X );
532 mbedtls_mpi_init( &pt->Y );
533 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100534}
535
536/*
537 * Initialize (the components of) a group
538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100540{
541 if( grp == NULL )
542 return;
543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100545}
546
547/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200548 * Initialize (the components of) a key pair
549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200551{
Paul Bakker66d5d072014-06-17 16:39:18 +0200552 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200553 return;
554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_ecp_group_init( &key->grp );
556 mbedtls_mpi_init( &key->d );
557 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200558}
559
560/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100561 * Unallocate (the components of) a point
562 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100564{
565 if( pt == NULL )
566 return;
567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 mbedtls_mpi_free( &( pt->X ) );
569 mbedtls_mpi_free( &( pt->Y ) );
570 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100571}
572
573/*
574 * Unallocate (the components of) a group
575 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100577{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200578 size_t i;
579
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100580 if( grp == NULL )
581 return;
582
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100583 if( grp->h != 1 )
584 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 mbedtls_mpi_free( &grp->P );
586 mbedtls_mpi_free( &grp->A );
587 mbedtls_mpi_free( &grp->B );
588 mbedtls_ecp_point_free( &grp->G );
589 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100590 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200591
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200592 if( grp->T != NULL )
593 {
594 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595 mbedtls_ecp_point_free( &grp->T[i] );
596 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200597 }
598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100600}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100601
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100602/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200603 * Unallocate (the components of) a key pair
604 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200605void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200606{
Paul Bakker66d5d072014-06-17 16:39:18 +0200607 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200608 return;
609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 mbedtls_ecp_group_free( &key->grp );
611 mbedtls_mpi_free( &key->d );
612 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200613}
614
615/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200616 * Copy the contents of a point
617 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200619{
620 int ret;
621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
623 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
624 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200625
626cleanup:
627 return( ret );
628}
629
630/*
631 * Copy the contents of a group object
632 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200634{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200635 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200636}
637
638/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100639 * Set point to zero
640 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100642{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100643 int ret;
644
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
646 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
647 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100648
649cleanup:
650 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100651}
652
653/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100654 * Tell if a point is zero
655 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100657{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100659}
660
661/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700662 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200663 */
664int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
665 const mbedtls_ecp_point *Q )
666{
667 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
668 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
669 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
670 {
671 return( 0 );
672 }
673
674 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
675}
676
677/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100678 * Import a non-zero point from ASCII strings
679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100681 const char *x, const char *y )
682{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100683 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
686 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
687 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100688
689cleanup:
690 return( ret );
691}
692
693/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100694 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100697 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100698 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100699{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200700 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100701 size_t plen;
702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
704 format != MBEDTLS_ECP_PF_COMPRESSED )
705 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100706
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100707 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100708 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100709 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100711 {
712 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100714
715 buf[0] = 0x00;
716 *olen = 1;
717
718 return( 0 );
719 }
720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100724 {
725 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100726
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100727 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100729
730 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
732 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100733 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100735 {
736 *olen = plen + 1;
737
738 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
742 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100743 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100744
745cleanup:
746 return( ret );
747}
748
749/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100750 * Import a point from unsigned binary data (SEC1 2.3.4)
751 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100753 const unsigned char *buf, size_t ilen )
754{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100755 int ret;
756 size_t plen;
757
Paul Bakker82788fb2014-10-20 13:59:19 +0200758 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200760
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100761 if( buf[0] == 0x00 )
762 {
763 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100765 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100767 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200769 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100770
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100771 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200772 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100773
774 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100776
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200777 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
778 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
779 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100780
781cleanup:
782 return( ret );
783}
784
785/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100786 * Import a point from a TLS ECPoint record (RFC 4492)
787 * struct {
788 * opaque point <1..2^8-1>;
789 * } ECPoint;
790 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200791int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100792 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100793{
794 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100795 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100796
797 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200798 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100799 */
800 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100802
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100803 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100804 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200805 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100806
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100807 /*
808 * Save buffer start for read_binary and update buf
809 */
810 buf_start = *buf;
811 *buf += data_len;
812
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200813 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100814}
815
816/*
817 * Export a point as a TLS ECPoint record (RFC 4492)
818 * struct {
819 * opaque point <1..2^8-1>;
820 * } ECPoint;
821 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200822int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100823 int format, size_t *olen,
824 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100825{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100826 int ret;
827
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100828 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100829 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100830 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100831 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200832 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100835 olen, buf + 1, blen - 1) ) != 0 )
836 return( ret );
837
838 /*
839 * write length to the first byte and update total length
840 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200841 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100842 ++*olen;
843
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200844 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100845}
846
847/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100848 * Set a group from an ECParameters record (RFC 4492)
849 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200850int 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 +0100851{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200852 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100854
855 /*
856 * We expect at least three bytes (see below)
857 */
858 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100860
861 /*
862 * First byte is curve_type; only named_curve is handled
863 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
865 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100866
867 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100868 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100869 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200870 tls_id = *(*buf)++;
871 tls_id <<= 8;
872 tls_id |= *(*buf)++;
873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
875 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200876
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200877 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100878}
879
880/*
881 * Write the ECParameters record corresponding to a group (RFC 4492)
882 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100884 unsigned char *buf, size_t blen )
885{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200887
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
889 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200890
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100891 /*
892 * We are going to write 3 bytes (see below)
893 */
894 *olen = 3;
895 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100897
898 /*
899 * First byte is curve_type, always named_curve
900 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200901 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100902
903 /*
904 * Next two bytes are the namedcurve value
905 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200906 buf[0] = curve_info->tls_id >> 8;
907 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100908
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200909 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100910}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100911
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200912/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200913 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
914 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200915 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200916 * 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 +0200917 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200919{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200920 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200921
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200922 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200923 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200924
925 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200926 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200927 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200928 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200930 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200931
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200932 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200933
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200934 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
936 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200937
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200938 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200939 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200940 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200941
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200942cleanup:
943 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200944}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200945
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100946/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100947 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100948 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100949 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200950 * 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 +0100951 * bring the result back to this range.
952 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100953 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100954 */
955
956/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200957 * 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 +0100958 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200959#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100960#define INC_MUL_COUNT mul_count++;
961#else
962#define INC_MUL_COUNT
963#endif
964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100966 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100967
968/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200970 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100971 */
972#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
974 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100975
976/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 * 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 +0200978 * We known P, N and the result are positive, so sub_abs is correct, and
979 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100980 */
981#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
983 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100984
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200985#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100986/*
987 * For curves in short Weierstrass form, we do all the internal operations in
988 * Jacobian coordinates.
989 *
990 * For multiplication, we'll use a comb method with coutermeasueres against
991 * SPA, hence timing attacks.
992 */
993
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100994/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100995 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100996 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100997 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200998static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100999{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001000 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001002
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001004 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001005
Janos Follathb0697532016-08-18 12:38:46 +01001006#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001007 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001008 {
Janos Follathc44ab972016-11-18 16:38:23 +00001009 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +01001010 }
Janos Follath372697b2016-10-28 16:53:11 +01001011#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001012 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001013
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001014 /*
1015 * X = X / Z^2 mod p
1016 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1018 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1019 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 +01001020
1021 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001022 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001023 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1025 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 +01001026
1027 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001028 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001030 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001031
1032cleanup:
1033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001035
1036 return( ret );
1037}
1038
1039/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001040 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001041 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001042 * (See for example Cohen's "A Course in Computational Algebraic Number
1043 * Theory", Algorithm 10.3.4.)
1044 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001045 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001046 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001047 *
1048 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001049 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001050static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1051 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001052{
1053 int ret;
1054 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001056
1057 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001058 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001059
Janos Follathb0697532016-08-18 12:38:46 +01001060#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001061 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001062 {
Janos Follathc44ab972016-11-18 16:38:23 +00001063 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001064 }
1065#endif
1066
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001067 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001068 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001070 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001071
1072 /*
1073 * c[i] = Z_0 * ... * Z_i
1074 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001076 for( i = 1; i < t_len; i++ )
1077 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001078 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001079 MOD_MUL( c[i] );
1080 }
1081
1082 /*
1083 * u = 1 / (Z_0 * ... * Z_n) mod P
1084 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001085 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001086
1087 for( i = t_len - 1; ; i-- )
1088 {
1089 /*
1090 * Zi = 1 / Z_i mod p
1091 * u = 1 / (Z_0 * ... * Z_i) mod P
1092 */
1093 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001095 }
1096 else
1097 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1099 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001100 }
1101
1102 /*
1103 * proceed as in normalize()
1104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1106 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1107 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1108 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 +01001109
1110 /*
1111 * Post-precessing: reclaim some memory by shrinking coordinates
1112 * - not storing Z (always 1)
1113 * - shrinking other coordinates, but still keeping the same number of
1114 * limbs as P, as otherwise it will too likely be regrown too fast.
1115 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1117 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1118 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001119
1120 if( i == 0 )
1121 break;
1122 }
1123
1124cleanup:
1125
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001126 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001127 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001128 mbedtls_mpi_free( &c[i] );
1129 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001130
1131 return( ret );
1132}
1133
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001134/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001135 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1136 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1139 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001140 unsigned char inv )
1141{
1142 int ret;
1143 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001147
1148 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1150 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1151 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001152
1153cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001154 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001155
1156 return( ret );
1157}
1158
1159/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001160 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001161 *
Peter Dettmance661b22015-02-07 14:43:51 +07001162 * 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 +01001163 *
Peter Dettmance661b22015-02-07 14:43:51 +07001164 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1165 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1166 *
1167 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1168 *
1169 * Cost: 1D := 3M + 4S (A == 0)
1170 * 4M + 4S (A == -3)
1171 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001172 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001173static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1174 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001175{
1176 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001177 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001179#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001180 dbl_count++;
1181#endif
1182
Janos Follathb0697532016-08-18 12:38:46 +01001183#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001184 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001185 {
Janos Follathc44ab972016-11-18 16:38:23 +00001186 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001187 }
Janos Follath372697b2016-10-28 16:53:11 +01001188#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001189
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001190 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 +01001191
1192 /* Special case for A = -3 */
1193 if( grp->A.p == NULL )
1194 {
Peter Dettmance661b22015-02-07 14:43:51 +07001195 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1198 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1199 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1200 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001201 }
1202 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001203 {
Peter Dettmance661b22015-02-07 14:43:51 +07001204 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001205 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1206 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001207
1208 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001209 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001210 {
1211 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001212 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1213 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001216 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001217 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001218
Peter Dettmance661b22015-02-07 14:43:51 +07001219 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001220 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1221 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1222 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1223 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001224
Peter Dettmance661b22015-02-07 14:43:51 +07001225 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001226 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1227 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001228
1229 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001230 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1231 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1232 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001233
1234 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001235 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1236 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1237 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001238
1239 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001240 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1241 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001242
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001243 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1244 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1245 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001246
1247cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001248 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 +02001249
1250 return( ret );
1251}
1252
1253/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001254 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001255 *
1256 * The coordinates of Q must be normalized (= affine),
1257 * but those of P don't need to. R is not normalized.
1258 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001259 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001260 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001261 * - at each step, P, Q and R are multiples of the base point, the factor
1262 * being less than its order, so none of them is zero;
1263 * - Q is an odd multiple of the base point, P an even multiple,
1264 * due to the choice of precomputed points in the modified comb method.
1265 * So branches for these cases do not leak secret information.
1266 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001267 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1268 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001269 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001270 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1272 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001273{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001274 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001276
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001277#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001278 add_count++;
1279#endif
1280
Janos Follathb0697532016-08-18 12:38:46 +01001281#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001282 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001283 {
Janos Follathc44ab972016-11-18 16:38:23 +00001284 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001285 }
Janos Follath372697b2016-10-28 16:53:11 +01001286#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001287
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001288 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001289 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001290 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1292 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001294 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1295 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001296
1297 /*
1298 * Make sure Q coordinates are normalized
1299 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001300 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1301 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1304 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001305
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001306 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1307 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1308 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1309 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1310 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1311 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001312
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001313 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001315 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001316 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001317 {
1318 ret = ecp_double_jac( grp, R, P );
1319 goto cleanup;
1320 }
1321 else
1322 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001323 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001324 goto cleanup;
1325 }
1326 }
1327
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001328 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1329 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1330 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1331 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1332 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1333 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1334 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1335 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1336 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1337 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1338 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1339 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001341 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001344
1345cleanup:
1346
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001347 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1348 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001349
1350 return( ret );
1351}
1352
1353/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001354 * Randomize jacobian coordinates:
1355 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001356 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001357 *
1358 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001359 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001361 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1362{
1363 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001364 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001365 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001366 int count = 0;
1367
Janos Follathb0697532016-08-18 12:38:46 +01001368#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001369 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001370 {
Janos Follathc44ab972016-11-18 16:38:23 +00001371 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001372 }
Janos Follath372697b2016-10-28 16:53:11 +01001373#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001374
1375 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001377
1378 /* Generate l such that 1 < l < p */
1379 do
1380 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001381 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001383 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1384 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001385
1386 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001387 {
1388 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1389 goto cleanup;
1390 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001391 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001393
1394 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 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 +02001396
1397 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001398 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1399 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 +02001400
1401 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001402 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1403 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 +02001404
1405cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001407
1408 return( ret );
1409}
1410
1411/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001412 * Check and define parameters used by the comb method (see below for details)
1413 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001414#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1415#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001416#endif
1417
1418/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001420
1421/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001422#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001423
1424/*
1425 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001426 *
1427 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001428 * modified version that provides resistance to SPA by avoiding zero
1429 * digits in the representation as in [3]. We modify the method further by
1430 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001431 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001432 *
1433 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1434 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1435 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001436 *
1437 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001438 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001439 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001440 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001441 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1442 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001443 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001444static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001445 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001446{
1447 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001448 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001449
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001450 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001451
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001452 /* First get the classical comb values (except for x_d = 0) */
1453 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001454 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001456
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001457 /* Now make sure x_1 .. x_d are odd */
1458 c = 0;
1459 for( i = 1; i <= d; i++ )
1460 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001461 /* Add carry and update it */
1462 cc = x[i] & c;
1463 x[i] = x[i] ^ c;
1464 c = cc;
1465
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001466 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001467 adjust = 1 - ( x[i] & 0x01 );
1468 c |= x[i] & ( x[i-1] * adjust );
1469 x[i] = x[i] ^ ( x[i-1] * adjust );
1470 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001471 }
1472}
1473
1474/*
1475 * Precompute points for the comb method
1476 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001477 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1478 * 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 +01001479 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001480 * T must be able to hold 2^{w - 1} elements
1481 *
1482 * 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 +01001483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1485 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001486 unsigned char w, size_t d )
1487{
1488 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001489 unsigned char i, k;
1490 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001492
1493 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001494 * Set T[0] = P and
1495 * 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 +01001496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001498
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001499 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001500 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001501 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001502 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001503 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001504 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001505 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001506
1507 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001508 }
1509
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001510 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001511
1512 /*
1513 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001514 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001515 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001516 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001517 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001518 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001519 j = i;
1520 while( j-- )
1521 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001522 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001523 TT[k++] = &T[i + j];
1524 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001525 }
1526
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001527 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001528
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001529cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001530
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001531 return( ret );
1532}
1533
1534/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001535 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1538 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001539 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001540{
1541 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001542 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001543
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001544 /* Ignore the "sign" bit and scale down */
1545 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001546
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001547 /* Read the whole table to thwart cache-based timing attacks */
1548 for( j = 0; j < t_len; j++ )
1549 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001550 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1551 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001552 }
1553
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001554 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001555 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001556
1557cleanup:
1558 return( ret );
1559}
1560
1561/*
1562 * Core multiplication algorithm for the (modified) comb method.
1563 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001564 *
1565 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001566 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1568 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001569 const unsigned char x[], size_t d,
1570 int (*f_rng)(void *, unsigned char *, size_t),
1571 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001572{
1573 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001574 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001575 size_t i;
1576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001577 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001578
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001579 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001580 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001581 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1582 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001583#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001584 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001585#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001587
1588 while( i-- != 0 )
1589 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001590 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1591 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1592 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001593 }
1594
1595cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001597 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001598
1599 return( ret );
1600}
1601
1602/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001603 * Multiplication using the comb method,
1604 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001605 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001606static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1607 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001608 int (*f_rng)(void *, unsigned char *, size_t),
1609 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001610{
1611 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001612 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1613 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001614 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001615 mbedtls_ecp_point *T;
1616 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001618 mbedtls_mpi_init( &M );
1619 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001620
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001621 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001622 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1623 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001624
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001625 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001626 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001627 * 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 +01001628 * (see costs of the various parts, with 1S = 1M)
1629 */
1630 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001631
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001632 /*
1633 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001634 * Just adding one avoids upping the cost of the first mul too much,
1635 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001636 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001637#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1638 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1639 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001640 if( p_eq_g )
1641 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001642#else
1643 p_eq_g = 0;
1644#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001645
1646 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001647 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001648 * (The last test is useful only for very small curves in the test suite.)
1649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001650 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1651 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001652 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001653 w = 2;
1654
1655 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001656 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001657 d = ( grp->nbits + w - 1 ) / w;
1658
1659 /*
1660 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001661 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001662 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001663 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001664
1665 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001666 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001667 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001668 if( T == NULL )
1669 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001670 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001671 goto cleanup;
1672 }
1673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001674 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001675
1676 if( p_eq_g )
1677 {
1678 grp->T = T;
1679 grp->T_size = pre_len;
1680 }
1681 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001682
1683 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001684 * Make sure M is odd (M = m or M = N - m, since N is odd)
1685 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001687 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1688 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1689 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1690 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001691
1692 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001693 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001694 */
1695 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001696 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 +01001697
1698 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001699 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001700 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001701 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001702
1703 /*
1704 * Knowledge of the jacobian coordinates may leak the last few bits of the
1705 * scalar [1], and since our MPI implementation isn't constant-flow,
1706 * inversion (used for coordinate normalization) may leak the full value
1707 * of its input via side-channels [2].
1708 *
1709 * [1] https://eprint.iacr.org/2003/191
1710 * [2] https://eprint.iacr.org/2020/055
1711 *
1712 * Avoid the leak by randomizing coordinates before we normalize them.
1713 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001714#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001715 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001716#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001717 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001719
1720cleanup:
1721
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001722 /* There are two cases where T is not stored in grp:
1723 * - P != G
1724 * - An intermediate operation failed before setting grp->T
1725 * In either case, T must be freed.
1726 */
1727 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001728 {
1729 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001730 mbedtls_ecp_point_free( &T[i] );
1731 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001732 }
1733
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001734 mbedtls_mpi_free( &M );
1735 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001736
1737 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001738 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001739
1740 return( ret );
1741}
1742
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001743#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001744
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001745#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001746/*
1747 * For Montgomery curves, we do all the internal arithmetic in projective
1748 * coordinates. Import/export of points uses only the x coordinates, which is
1749 * internaly represented as X / Z.
1750 *
1751 * For scalar multiplication, we'll use a Montgomery ladder.
1752 */
1753
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001754/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001755 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1756 * Cost: 1M + 1I
1757 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001759{
1760 int ret;
1761
Janos Follathb0697532016-08-18 12:38:46 +01001762#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001763 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001764 {
Janos Follathc44ab972016-11-18 16:38:23 +00001765 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001766 }
Janos Follath372697b2016-10-28 16:53:11 +01001767#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001768
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001769 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1770 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1771 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001772
1773cleanup:
1774 return( ret );
1775}
1776
1777/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001778 * Randomize projective x/z coordinates:
1779 * (X, Z) -> (l X, l Z) for random l
1780 * This is sort of the reverse operation of ecp_normalize_mxz().
1781 *
1782 * This countermeasure was first suggested in [2].
1783 * Cost: 2M
1784 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001785static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001786 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1787{
1788 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001790 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001791 int count = 0;
1792
Janos Follathb0697532016-08-18 12:38:46 +01001793#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001794 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001795 {
Janos Follathc44ab972016-11-18 16:38:23 +00001796 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001797 }
Janos Follath372697b2016-10-28 16:53:11 +01001798#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001799
1800 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001801 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001802
1803 /* Generate l such that 1 < l < p */
1804 do
1805 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001806 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001810
1811 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001812 {
1813 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1814 goto cleanup;
1815 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001816 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001817 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001818
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1820 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 +01001821
1822cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001823 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001824
1825 return( ret );
1826}
1827
1828/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001829 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1830 * for Montgomery curves in x/z coordinates.
1831 *
1832 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1833 * with
1834 * d = X1
1835 * P = (X2, Z2)
1836 * Q = (X3, Z3)
1837 * R = (X4, Z4)
1838 * S = (X5, Z5)
1839 * and eliminating temporary variables tO, ..., t4.
1840 *
1841 * Cost: 5M + 4S
1842 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001843static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1844 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1845 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1846 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001847{
1848 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001849 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001850
Janos Follathb0697532016-08-18 12:38:46 +01001851#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001852 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001853 {
Janos Follathc44ab972016-11-18 16:38:23 +00001854 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001855 }
Janos Follath372697b2016-10-28 16:53:11 +01001856#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001858 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1859 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1860 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001862 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1868 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1869 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1870 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1871 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1872 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1873 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1874 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1875 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1876 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1877 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1878 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1879 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 +01001880
1881cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1883 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1884 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001885
1886 return( ret );
1887}
1888
1889/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001890 * Multiplication with Montgomery ladder in x/z coordinates,
1891 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001892 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1894 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001895 int (*f_rng)(void *, unsigned char *, size_t),
1896 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001897{
1898 int ret;
1899 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001900 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001901 mbedtls_ecp_point RP;
1902 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001903
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001904 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001905
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001906 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001907 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1908 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001909
1910 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1912 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1913 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001914
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001915 /* RP.X might be sligtly larger than P, so reduce it */
1916 MOD_ADD( RP.X );
1917
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001918 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001919#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001920 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001921#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001923
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001924 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001925 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001926 while( i-- > 0 )
1927 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001929 /*
1930 * if (b) R = 2R + P else R = 2R,
1931 * which is:
1932 * if (b) double_add( RP, R, RP, R )
1933 * else double_add( R, RP, R, RP )
1934 * but using safe conditional swaps to avoid leaks
1935 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001936 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1937 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1938 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1939 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1940 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001941 }
1942
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001943 /*
1944 * Knowledge of the projective coordinates may leak the last few bits of the
1945 * scalar [1], and since our MPI implementation isn't constant-flow,
1946 * inversion (used for coordinate normalization) may leak the full value
1947 * of its input via side-channels [2].
1948 *
1949 * [1] https://eprint.iacr.org/2003/191
1950 * [2] https://eprint.iacr.org/2020/055
1951 *
1952 * Avoid the leak by randomizing coordinates before we normalize them.
1953 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001954#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001955 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001956#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001957 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1958
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001959 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001960
1961cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001962 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001963
1964 return( ret );
1965}
1966
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001967#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001968
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001969/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001970 * Multiplication R = m * P
1971 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001972int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1973 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001974 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1975{
Janos Follathb0697532016-08-18 12:38:46 +01001976 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001977#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1978 char is_grp_capable = 0;
1979#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001980#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1981 ecp_drbg_context drbg_ctx;
1982
1983 ecp_drbg_init( &drbg_ctx );
1984#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001985
1986 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001987 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1988 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001989
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001990 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1991 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001992 return( ret );
1993
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001994#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1995 if( f_rng == NULL )
1996 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02001997 const size_t m_len = ( grp->nbits + 7 ) / 8;
1998 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001999 f_rng = &ecp_drbg_random;
2000 p_rng = &drbg_ctx;
2001 }
2002#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
2003
Janos Follathc44ab972016-11-18 16:38:23 +00002004#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002005 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002006 {
Janos Follathc44ab972016-11-18 16:38:23 +00002007 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002008 }
Janos Follathc44ab972016-11-18 16:38:23 +00002009#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002010
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002011#if defined(ECP_MONTGOMERY)
2012 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002013 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002014#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002015#if defined(ECP_SHORTWEIERSTRASS)
2016 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002017 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002018#endif
Janos Follathb0697532016-08-18 12:38:46 +01002019
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002020#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2021cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002022#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002023#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002024 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002025 {
Janos Follathc44ab972016-11-18 16:38:23 +00002026 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002027 }
Janos Follathc44ab972016-11-18 16:38:23 +00002028#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002029
2030#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2031 ecp_drbg_free( &drbg_ctx );
2032#endif
2033
Janos Follathb0697532016-08-18 12:38:46 +01002034 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002035}
2036
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002037#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002038/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002039 * Check that an affine point is valid as a public key,
2040 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002042static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002043{
2044 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002045 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002046
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002047 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002048 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2049 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2050 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2051 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2052 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002053
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002054 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002055
2056 /*
2057 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002058 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002059 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002060 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2061 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002062
2063 /* Special case for A = -3 */
2064 if( grp->A.p == NULL )
2065 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002066 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002067 }
2068 else
2069 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002071 }
2072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002073 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2074 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002075
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002076 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2077 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002078
2079cleanup:
2080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002081 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002082
2083 return( ret );
2084}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002085#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002086
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002087/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002088 * R = m * P with shortcuts for m == 1 and m == -1
2089 * NOT constant-time - ONLY for short Weierstrass!
2090 */
2091static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2092 mbedtls_ecp_point *R,
2093 const mbedtls_mpi *m,
2094 const mbedtls_ecp_point *P )
2095{
2096 int ret;
2097
2098 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2099 {
2100 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2101 }
2102 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2103 {
2104 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2105 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2107 }
2108 else
2109 {
2110 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2111 }
2112
2113cleanup:
2114 return( ret );
2115}
2116
2117/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002118 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002119 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002120 */
2121int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2122 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2123 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2124{
2125 int ret;
2126 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002127#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2128 char is_grp_capable = 0;
2129#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002130
2131 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2132 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2133
2134 mbedtls_ecp_point_init( &mP );
2135
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002136 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2137 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002138
Janos Follathc44ab972016-11-18 16:38:23 +00002139#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002140 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002141 {
Janos Follathc44ab972016-11-18 16:38:23 +00002142 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002143 }
Janos Follath430d3372016-11-03 14:25:37 +00002144
Janos Follathc44ab972016-11-18 16:38:23 +00002145#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002146 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2147 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2148
2149cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002150
Janos Follathc44ab972016-11-18 16:38:23 +00002151#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2152 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002153 {
Janos Follathc44ab972016-11-18 16:38:23 +00002154 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002155 }
Janos Follathb0697532016-08-18 12:38:46 +01002156
Janos Follathc44ab972016-11-18 16:38:23 +00002157#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002158 mbedtls_ecp_point_free( &mP );
2159
2160 return( ret );
2161}
2162
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002163
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002164#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002165/*
2166 * Check validity of a public key for Montgomery curves with x-only schemes
2167 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002168static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002169{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002170 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2172 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002173
2174 return( 0 );
2175}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002176#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002177
2178/*
2179 * Check that a point is valid as a public key
2180 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002182{
2183 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2185 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002186
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002187#if defined(ECP_MONTGOMERY)
2188 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002189 return( ecp_check_pubkey_mx( grp, pt ) );
2190#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002191#if defined(ECP_SHORTWEIERSTRASS)
2192 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002193 return( ecp_check_pubkey_sw( grp, pt ) );
2194#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002195 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002196}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002197
2198/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002199 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002200 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002201int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002202{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002203#if defined(ECP_MONTGOMERY)
2204 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002205 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002206 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002207 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2208 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2209 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002210 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002212 else
2213 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002214 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002215#endif /* ECP_MONTGOMERY */
2216#if defined(ECP_SHORTWEIERSTRASS)
2217 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002218 {
2219 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002220 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2221 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2222 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002223 else
2224 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002225 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002226#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002227
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002229}
2230
2231/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002232 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002233 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002234int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2235 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002236 int (*f_rng)(void *, unsigned char *, size_t),
2237 void *p_rng )
2238{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002239 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002240 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002241
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002242#if defined(ECP_MONTGOMERY)
2243 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002244 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002245 /* [M225] page 5 */
2246 size_t b;
2247
Janos Follath98e28a72016-05-31 14:03:54 +01002248 do {
2249 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2250 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002251
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002252 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002253 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002254 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002255 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002256 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002257 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002258
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002259 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002260 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2261 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2262 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002263 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002264#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002265
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002266#if defined(ECP_SHORTWEIERSTRASS)
2267 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002268 {
2269 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002270 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002271 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002272
2273 /*
2274 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2275 * - use the same byte ordering;
2276 * - keep the leftmost nbits bits of the generated octet string;
2277 * - try until result is in the desired range.
2278 * This also avoids any biais, which is especially important for ECDSA.
2279 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002280 do
2281 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002282 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002283 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002284
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002285 /*
2286 * Each try has at worst a probability 1/2 of failing (the msb has
2287 * a probability 1/2 of being 0, and then the result will be < N),
2288 * so after 30 tries failure probability is a most 2**(-30).
2289 *
2290 * For most curves, 1 try is enough with overwhelming probability,
2291 * since N starts with a lot of 1s in binary, but some curves
2292 * such as secp224k1 are actually very close to the worst case.
2293 */
2294 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002295 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002296
Janos Follathc3b376e2019-10-11 14:21:53 +01002297 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002298 if( ret != 0 )
2299 {
2300 goto cleanup;
2301 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002302 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002303 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002304 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002305#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002306
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002307cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002308 return( ret );
2309}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002310
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002311/*
2312 * Generate a keypair with configurable base point
2313 */
2314int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2315 const mbedtls_ecp_point *G,
2316 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2317 int (*f_rng)(void *, unsigned char *, size_t),
2318 void *p_rng )
2319{
2320 int ret;
2321
2322 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2323 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2324
2325cleanup:
2326 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002327}
2328
2329/*
2330 * Generate key pair, wrapper for conventional base point
2331 */
2332int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2333 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2334 int (*f_rng)(void *, unsigned char *, size_t),
2335 void *p_rng )
2336{
2337 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002338}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002339
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002340/*
2341 * Generate a keypair, prettier wrapper
2342 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002343int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002344 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2345{
2346 int ret;
2347
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002348 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002349 return( ret );
2350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002352}
2353
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002354/*
2355 * Check a public-private key pair
2356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002357int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002358{
2359 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_ecp_point Q;
2361 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002362
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002363 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002364 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002365 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2366 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2367 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002369 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002370 }
2371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002372 mbedtls_ecp_point_init( &Q );
2373 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 /* mbedtls_ecp_mul() needs a non-const group... */
2376 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002377
2378 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002381 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2382 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2383 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002384 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002386 goto cleanup;
2387 }
2388
2389cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002390 mbedtls_ecp_point_free( &Q );
2391 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002392
2393 return( ret );
2394}
2395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002396#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002397
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002398#if defined(ECP_ONE_STEP_KDF)
2399/*
2400 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2401 * but unofficial ones can be found at:
2402 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2403 *
2404 * We only use the ones with empty fixedInfo, and for brevity's sake, only
2405 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
2406 * exactly one block, and with SHA-512 less than one block).
2407 */
2408#if defined(MBEDTLS_SHA512_C)
2409
2410static const uint8_t test_kdf_z[16] = {
2411 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
2412 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
2413};
2414static const uint8_t test_kdf_out[32] = {
2415 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
2416 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
2417 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
2418 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
2419};
2420
2421#elif defined(MBEDTLS_SHA256_C)
2422
2423static const uint8_t test_kdf_z[16] = {
2424 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
2425 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
2426};
2427static const uint8_t test_kdf_out[32] = {
2428 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
2429 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
2430 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
2431 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
2432};
2433
2434#elif defined(MBEDTLS_SHA1_C)
2435
2436static const uint8_t test_kdf_z[16] = {
2437 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
2438 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
2439};
2440static const uint8_t test_kdf_out[32] = {
2441 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
2442 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
2443 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
2444 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
2445};
2446
2447#else
2448#error "Need at least one of SHA-512, SHA-256 or SHA-1"
2449#endif
2450
2451static int ecp_kdf_self_test( void )
2452{
2453 int ret;
2454 ecp_drbg_context kdf_ctx;
2455 mbedtls_mpi scalar;
2456 uint8_t out[sizeof( test_kdf_out )];
2457
2458 ecp_drbg_init( &kdf_ctx );
2459 mbedtls_mpi_init( &scalar );
2460 memset( out, 0, sizeof( out ) );
2461
2462 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2463 test_kdf_z, sizeof( test_kdf_z ) ) );
2464
2465 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2466 &scalar, sizeof( test_kdf_z ) ) );
2467
2468 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2469
2470 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2471 ret = -1;
2472
2473cleanup:
2474 ecp_drbg_free( &kdf_ctx );
2475 mbedtls_mpi_free( &scalar );
2476
2477 return( ret );
2478}
2479#endif /* ECP_ONE_STEP_KDF */
2480
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002481/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002482 * Checkup routine
2483 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002484int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002485{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002486 int ret;
2487 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002488 mbedtls_ecp_group grp;
2489 mbedtls_ecp_point R, P;
2490 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002491 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002492 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002493 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002494 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002495 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002496 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002497 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002498 "400000000000000000000000000000000000000000000000", /* one and zeros */
2499 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2500 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002501 };
2502
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002503 mbedtls_ecp_group_init( &grp );
2504 mbedtls_ecp_point_init( &R );
2505 mbedtls_ecp_point_init( &P );
2506 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002507
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002508 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002509#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002510 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002511#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002512 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002513#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002514
2515 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002516 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002517
2518 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002519 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2520 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002521
2522 add_count = 0;
2523 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002524 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002525 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2526 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002527
2528 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2529 {
2530 add_c_prev = add_count;
2531 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002532 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002533 add_count = 0;
2534 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002535 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002537 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2538 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002539
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002540 if( add_count != add_c_prev ||
2541 dbl_count != dbl_c_prev ||
2542 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002543 {
2544 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002546
2547 ret = 1;
2548 goto cleanup;
2549 }
2550 }
2551
2552 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002553 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002554
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002555 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002556 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002557 /* We computed P = 2G last time, use it */
2558
2559 add_count = 0;
2560 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002561 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002562 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2563 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002564
2565 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2566 {
2567 add_c_prev = add_count;
2568 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002569 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002570 add_count = 0;
2571 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002572 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002573
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002574 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2575 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002576
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002577 if( add_count != add_c_prev ||
2578 dbl_count != dbl_c_prev ||
2579 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002580 {
2581 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002582 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002583
2584 ret = 1;
2585 goto cleanup;
2586 }
2587 }
2588
2589 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002590 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002591
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002592#if defined(ECP_ONE_STEP_KDF)
2593 if( verbose != 0 )
2594 mbedtls_printf( " ECP test #3 (internal KDF): " );
2595
2596 ret = ecp_kdf_self_test();
2597 if( ret != 0 )
2598 {
2599 if( verbose != 0 )
2600 mbedtls_printf( "failed\n" );
2601
2602 ret = 1;
2603 goto cleanup;
2604 }
2605
2606 if( verbose != 0 )
2607 mbedtls_printf( "passed\n" );
2608#endif /* ECP_ONE_STEP_KDF */
2609
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002610cleanup:
2611
2612 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002613 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615 mbedtls_ecp_group_free( &grp );
2616 mbedtls_ecp_point_free( &R );
2617 mbedtls_ecp_point_free( &P );
2618 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002619
2620 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002621 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002622
2623 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002624}
2625
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002626#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002627
Janos Follathb0697532016-08-18 12:38:46 +01002628#endif /* !MBEDTLS_ECP_ALT */
2629
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002630#endif /* MBEDTLS_ECP_C */