blob: 88786b3998496d233534448bc0e6539221b6cd63 [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{
151 const unsigned char *secret_p = (const unsigned char *) secret->p;
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200152
153 /* 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é-Gonnard6d614982020-06-16 12:51:42 +0200157 return( mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_p, secret_len ) );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200158}
159
160#elif defined(MBEDTLS_CTR_DRBG_C)
161
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200162/* DRBG context type */
163typedef mbedtls_ctr_drbg_context ecp_drbg_context;
164
165/* DRBG context init */
166static inline void ecp_drbg_init( ecp_drbg_context *ctx )
167{
168 mbedtls_ctr_drbg_init( ctx );
169}
170
171/* DRBG context free */
172static inline void ecp_drbg_free( ecp_drbg_context *ctx )
173{
174 mbedtls_ctr_drbg_free( ctx );
175}
176
177/* DRBG function */
178static inline int ecp_drbg_random( void *p_rng,
179 unsigned char *output, size_t output_len )
180{
181 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
182}
183
184/*
185 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
186 * we need to pass an entropy function when seeding. So we use a dummy
187 * function for that, and pass the actual entropy as customisation string.
188 * (During seeding of CTR_DRBG the entropy input and customisation string are
189 * concatenated before being used to update the secret state.)
190 */
191static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
192{
193 (void) ctx;
194 memset( out, 0, len );
195 return( 0 );
196}
197
198/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200199static int ecp_drbg_seed( ecp_drbg_context *ctx,
200 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200201{
202 const unsigned char *secret_p = (const unsigned char *) secret->p;
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200203
204 return( mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200205 secret_p, secret_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200206}
207
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200208#elif defined(MBEDTLS_SHA512_C) || \
209 defined(MBEDTLS_SHA256_C) || \
210 defined(MBEDTLS_SHA1_C)
211
212/* This will be used in the self-test function */
213#define ECP_ONE_STEP_KDF
214
215/*
216 * We need to expand secret data (the scalar) into a longer stream of bytes.
217 *
218 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
219 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
220 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
221 *
222 * We need a basic hash abstraction layer to use whatever SHA is available.
223 */
224#if defined(MBEDTLS_SHA512_C)
225
226#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
227#define HASH_BLOCK_BYTES ( 512 / 8 )
228
229#elif defined(MBEDTLS_SHA256_C)
230
231#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
232#define HASH_BLOCK_BYTES ( 256 / 8 )
233
234#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
235
236#define HASH_FUNC mbedtls_sha1_ret
237#define HASH_BLOCK_BYTES ( 160 / 8 )
238
239#endif /* SHA512/SHA256/SHA1 abstraction */
240
241/*
242 * State consists of a 32-bit counter plus the secret value.
243 *
244 * We stored them concatenated in a single buffer as that's what will get
245 * passed to the hash function.
246 */
247typedef struct {
248 size_t total_len;
249 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
250} ecp_drbg_context;
251
252static void ecp_drbg_init( ecp_drbg_context *ctx )
253{
254 memset( ctx, 0, sizeof( ecp_drbg_context ) );
255}
256
257static void ecp_drbg_free( ecp_drbg_context *ctx )
258{
259 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
260}
261
262static int ecp_drbg_seed( ecp_drbg_context *ctx,
263 const mbedtls_mpi *secret, size_t secret_len )
264{
265 ctx->total_len = 4 + secret_len;
266 memset( ctx->buf, 0, 4);
267 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
268}
269
270static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
271{
272 ecp_drbg_context *ctx = p_rng;
273 int ret;
274 size_t len_done = 0;
275
276 while( len_done < output_len )
277 {
278 uint8_t tmp[HASH_BLOCK_BYTES];
279 uint8_t use_len;
280
281 /* We don't need to draw more that 255 blocks, so don't bother with
282 * carry propagation and just return an error instead. */
283 ctx->buf[3] += 1;
284 if( ctx->buf[3] == 0 )
285 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
286
287 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
288 if( ret != 0 )
289 return( ret );
290
291 if( output_len - len_done > HASH_BLOCK_BYTES )
292 use_len = HASH_BLOCK_BYTES;
293 else
294 use_len = output_len - len_done;
295
296 memcpy( output + len_done, tmp, use_len );
297 len_done += use_len;
298 }
299
300 return( 0 );
301}
302
303#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200304#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200305#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200306#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
307
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
309 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
310 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
311 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
312 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
313 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
314 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
315 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
316 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
317 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
318 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200319#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100320#endif
321
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200322#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200323#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100324#endif
325
326/*
327 * Curve types: internal for now, might be exposed later
328 */
329typedef enum
330{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200331 ECP_TYPE_NONE = 0,
332 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
333 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100334} ecp_curve_type;
335
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100336/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200337 * List of supported curves:
338 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200339 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200340 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200341 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100342 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100343 * Curves are listed in order: largest curves first, and for a given size,
344 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200345 *
346 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200349{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
351 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200352#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
354 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100355#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
357 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200358#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
360 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100361#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200362#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
363 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200364#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
366 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100367#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
369 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100370#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
372 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200373#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200374#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
375 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100376#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
378 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100379#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
381 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100382#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200384};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100385
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200386#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
387 sizeof( ecp_supported_curves[0] )
388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200390
391/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200392 * List of supported curves and associated info
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200395{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200396 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200397}
398
399/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100400 * List of supported curves, group ID only
401 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100403{
404 static int init_done = 0;
405
406 if( ! init_done )
407 {
408 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 for( curve_info = mbedtls_ecp_curve_list();
412 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100413 curve_info++ )
414 {
415 ecp_supported_grp_id[i++] = curve_info->grp_id;
416 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100418
419 init_done = 1;
420 }
421
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200422 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100423}
424
425/*
426 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200427 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428const 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 +0200429{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200431
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 for( curve_info = mbedtls_ecp_curve_list();
433 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200434 curve_info++ )
435 {
436 if( curve_info->grp_id == grp_id )
437 return( curve_info );
438 }
439
440 return( NULL );
441}
442
443/*
444 * Get the curve info from the TLS identifier
445 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200447{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 for( curve_info = mbedtls_ecp_curve_list();
451 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200452 curve_info++ )
453 {
454 if( curve_info->tls_id == tls_id )
455 return( curve_info );
456 }
457
458 return( NULL );
459}
460
461/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100462 * Get the curve info from the name
463 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100465{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 for( curve_info = mbedtls_ecp_curve_list();
469 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100470 curve_info++ )
471 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200472 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100473 return( curve_info );
474 }
475
476 return( NULL );
477}
478
479/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100480 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100481 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100483{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100484 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200485 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100486
487 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200488 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100489 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200490 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100491}
492
493/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100494 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100497{
498 if( pt == NULL )
499 return;
500
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501 mbedtls_mpi_init( &pt->X );
502 mbedtls_mpi_init( &pt->Y );
503 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100504}
505
506/*
507 * Initialize (the components of) a group
508 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100510{
511 if( grp == NULL )
512 return;
513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100515}
516
517/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200518 * Initialize (the components of) a key pair
519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200521{
Paul Bakker66d5d072014-06-17 16:39:18 +0200522 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200523 return;
524
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525 mbedtls_ecp_group_init( &key->grp );
526 mbedtls_mpi_init( &key->d );
527 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200528}
529
530/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100531 * Unallocate (the components of) a point
532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100534{
535 if( pt == NULL )
536 return;
537
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200538 mbedtls_mpi_free( &( pt->X ) );
539 mbedtls_mpi_free( &( pt->Y ) );
540 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100541}
542
543/*
544 * Unallocate (the components of) a group
545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100547{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200548 size_t i;
549
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100550 if( grp == NULL )
551 return;
552
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100553 if( grp->h != 1 )
554 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 mbedtls_mpi_free( &grp->P );
556 mbedtls_mpi_free( &grp->A );
557 mbedtls_mpi_free( &grp->B );
558 mbedtls_ecp_point_free( &grp->G );
559 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100560 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200561
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200562 if( grp->T != NULL )
563 {
564 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565 mbedtls_ecp_point_free( &grp->T[i] );
566 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200567 }
568
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200569 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100570}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100571
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100572/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200573 * Unallocate (the components of) a key pair
574 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200575void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200576{
Paul Bakker66d5d072014-06-17 16:39:18 +0200577 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200578 return;
579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 mbedtls_ecp_group_free( &key->grp );
581 mbedtls_mpi_free( &key->d );
582 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200583}
584
585/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200586 * Copy the contents of a point
587 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200589{
590 int ret;
591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
593 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
594 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200595
596cleanup:
597 return( ret );
598}
599
600/*
601 * Copy the contents of a group object
602 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200604{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200605 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200606}
607
608/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100609 * Set point to zero
610 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100612{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100613 int ret;
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
616 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
617 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100618
619cleanup:
620 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100621}
622
623/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100624 * Tell if a point is zero
625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100627{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100629}
630
631/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700632 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200633 */
634int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
635 const mbedtls_ecp_point *Q )
636{
637 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
638 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
639 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
640 {
641 return( 0 );
642 }
643
644 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
645}
646
647/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100648 * Import a non-zero point from ASCII strings
649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100651 const char *x, const char *y )
652{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100653 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
656 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
657 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100658
659cleanup:
660 return( ret );
661}
662
663/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100664 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100665 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100667 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100668 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100669{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200670 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100671 size_t plen;
672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
674 format != MBEDTLS_ECP_PF_COMPRESSED )
675 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100676
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100677 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100678 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100681 {
682 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100684
685 buf[0] = 0x00;
686 *olen = 1;
687
688 return( 0 );
689 }
690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100692
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100694 {
695 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100696
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100697 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100699
700 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
702 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100703 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100705 {
706 *olen = plen + 1;
707
708 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
712 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100713 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100714
715cleanup:
716 return( ret );
717}
718
719/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100720 * Import a point from unsigned binary data (SEC1 2.3.4)
721 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100723 const unsigned char *buf, size_t ilen )
724{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100725 int ret;
726 size_t plen;
727
Paul Bakker82788fb2014-10-20 13:59:19 +0200728 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200730
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100731 if( buf[0] == 0x00 )
732 {
733 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100735 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100737 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100740
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100741 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100743
744 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200745 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100746
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200747 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
748 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
749 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100750
751cleanup:
752 return( ret );
753}
754
755/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100756 * Import a point from a TLS ECPoint record (RFC 4492)
757 * struct {
758 * opaque point <1..2^8-1>;
759 * } ECPoint;
760 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100762 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100763{
764 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100765 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100766
767 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200768 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100769 */
770 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200771 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100772
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100773 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100774 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200775 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100776
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100777 /*
778 * Save buffer start for read_binary and update buf
779 */
780 buf_start = *buf;
781 *buf += data_len;
782
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200783 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100784}
785
786/*
787 * Export a point as a TLS ECPoint record (RFC 4492)
788 * struct {
789 * opaque point <1..2^8-1>;
790 * } ECPoint;
791 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100793 int format, size_t *olen,
794 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100795{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100796 int ret;
797
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100798 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100799 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100800 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100801 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100803
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100805 olen, buf + 1, blen - 1) ) != 0 )
806 return( ret );
807
808 /*
809 * write length to the first byte and update total length
810 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200811 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100812 ++*olen;
813
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200814 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100815}
816
817/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100818 * Set a group from an ECParameters record (RFC 4492)
819 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200820int 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 +0100821{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200822 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100824
825 /*
826 * We expect at least three bytes (see below)
827 */
828 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200829 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100830
831 /*
832 * First byte is curve_type; only named_curve is handled
833 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
835 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100836
837 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100838 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100839 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200840 tls_id = *(*buf)++;
841 tls_id <<= 8;
842 tls_id |= *(*buf)++;
843
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200844 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
845 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200846
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200847 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100848}
849
850/*
851 * Write the ECParameters record corresponding to a group (RFC 4492)
852 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100854 unsigned char *buf, size_t blen )
855{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200856 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200857
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200858 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
859 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200860
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100861 /*
862 * We are going to write 3 bytes (see below)
863 */
864 *olen = 3;
865 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200866 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100867
868 /*
869 * First byte is curve_type, always named_curve
870 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200871 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100872
873 /*
874 * Next two bytes are the namedcurve value
875 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200876 buf[0] = curve_info->tls_id >> 8;
877 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100878
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200879 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100880}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100881
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200882/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200883 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
884 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200885 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 * 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 +0200887 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200888static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200889{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200890 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200891
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200892 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200894
895 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200896 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200897 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200898 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200900 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200901
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200903
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200904 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
906 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200907
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200908 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200909 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200910 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200911
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200912cleanup:
913 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200914}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200915
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100916/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100917 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100918 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100919 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200920 * 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 +0100921 * bring the result back to this range.
922 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100923 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100924 */
925
926/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 * 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 +0100928 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100930#define INC_MUL_COUNT mul_count++;
931#else
932#define INC_MUL_COUNT
933#endif
934
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200935#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100936 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100937
938/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200940 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100941 */
942#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200943 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
944 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100945
946/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 * 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 +0200948 * We known P, N and the result are positive, so sub_abs is correct, and
949 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100950 */
951#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200952 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
953 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100954
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200955#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100956/*
957 * For curves in short Weierstrass form, we do all the internal operations in
958 * Jacobian coordinates.
959 *
960 * For multiplication, we'll use a comb method with coutermeasueres against
961 * SPA, hence timing attacks.
962 */
963
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100964/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100965 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100966 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100967 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200968static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100969{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100970 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200971 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100972
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200973 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100974 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100975
Janos Follathb0697532016-08-18 12:38:46 +0100976#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000977 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100978 {
Janos Follathc44ab972016-11-18 16:38:23 +0000979 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +0100980 }
Janos Follath372697b2016-10-28 16:53:11 +0100981#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200982 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100983
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100984 /*
985 * X = X / Z^2 mod p
986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
988 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
989 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 +0100990
991 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100992 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100993 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200994 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
995 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 +0100996
997 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100998 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100999 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001000 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001001
1002cleanup:
1003
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001004 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001005
1006 return( ret );
1007}
1008
1009/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001010 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001011 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001012 * (See for example Cohen's "A Course in Computational Algebraic Number
1013 * Theory", Algorithm 10.3.4.)
1014 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001015 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001016 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001017 *
1018 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001019 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001020static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1021 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001022{
1023 int ret;
1024 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001025 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001026
1027 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001028 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001029
Janos Follathb0697532016-08-18 12:38:46 +01001030#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001031 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001032 {
Janos Follathc44ab972016-11-18 16:38:23 +00001033 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001034 }
1035#endif
1036
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001037 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001038 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001039
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001040 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001041
1042 /*
1043 * c[i] = Z_0 * ... * Z_i
1044 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001045 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001046 for( i = 1; i < t_len; i++ )
1047 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001049 MOD_MUL( c[i] );
1050 }
1051
1052 /*
1053 * u = 1 / (Z_0 * ... * Z_n) mod P
1054 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001055 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001056
1057 for( i = t_len - 1; ; i-- )
1058 {
1059 /*
1060 * Zi = 1 / Z_i mod p
1061 * u = 1 / (Z_0 * ... * Z_i) mod P
1062 */
1063 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001065 }
1066 else
1067 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001068 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1069 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001070 }
1071
1072 /*
1073 * proceed as in normalize()
1074 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001075 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1076 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1077 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1078 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 +01001079
1080 /*
1081 * Post-precessing: reclaim some memory by shrinking coordinates
1082 * - not storing Z (always 1)
1083 * - shrinking other coordinates, but still keeping the same number of
1084 * limbs as P, as otherwise it will too likely be regrown too fast.
1085 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001086 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1087 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1088 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001089
1090 if( i == 0 )
1091 break;
1092 }
1093
1094cleanup:
1095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001096 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001097 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001098 mbedtls_mpi_free( &c[i] );
1099 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001100
1101 return( ret );
1102}
1103
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001104/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001105 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1106 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1107 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001108static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1109 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001110 unsigned char inv )
1111{
1112 int ret;
1113 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001114 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001115
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001116 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001117
1118 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001119 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1120 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1121 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001122
1123cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001124 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001125
1126 return( ret );
1127}
1128
1129/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001130 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001131 *
Peter Dettmance661b22015-02-07 14:43:51 +07001132 * 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 +01001133 *
Peter Dettmance661b22015-02-07 14:43:51 +07001134 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1135 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1136 *
1137 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1138 *
1139 * Cost: 1D := 3M + 4S (A == 0)
1140 * 4M + 4S (A == -3)
1141 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001142 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1144 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001145{
1146 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001147 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001148
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001149#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001150 dbl_count++;
1151#endif
1152
Janos Follathb0697532016-08-18 12:38:46 +01001153#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001154 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001155 {
Janos Follathc44ab972016-11-18 16:38:23 +00001156 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001157 }
Janos Follath372697b2016-10-28 16:53:11 +01001158#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001159
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001160 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 +01001161
1162 /* Special case for A = -3 */
1163 if( grp->A.p == NULL )
1164 {
Peter Dettmance661b22015-02-07 14:43:51 +07001165 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001166 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1167 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1168 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1169 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1170 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001171 }
1172 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001173 {
Peter Dettmance661b22015-02-07 14:43:51 +07001174 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001175 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1176 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001177
1178 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001179 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001180 {
1181 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001182 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1183 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1184 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1185 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001186 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001187 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001188
Peter Dettmance661b22015-02-07 14:43:51 +07001189 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001190 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1191 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1192 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1193 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001194
Peter Dettmance661b22015-02-07 14:43:51 +07001195 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001196 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1197 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001198
1199 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001200 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1201 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1202 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001203
1204 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1206 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1207 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001208
1209 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1211 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001212
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001213 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1214 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1215 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001216
1217cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001218 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 +02001219
1220 return( ret );
1221}
1222
1223/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001224 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001225 *
1226 * The coordinates of Q must be normalized (= affine),
1227 * but those of P don't need to. R is not normalized.
1228 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001229 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001230 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001231 * - at each step, P, Q and R are multiples of the base point, the factor
1232 * being less than its order, so none of them is zero;
1233 * - Q is an odd multiple of the base point, P an even multiple,
1234 * due to the choice of precomputed points in the modified comb method.
1235 * So branches for these cases do not leak secret information.
1236 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001237 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1238 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001239 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001240 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001241static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1242 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001243{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001244 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001247#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001248 add_count++;
1249#endif
1250
Janos Follathb0697532016-08-18 12:38:46 +01001251#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001252 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001253 {
Janos Follathc44ab972016-11-18 16:38:23 +00001254 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001255 }
Janos Follath372697b2016-10-28 16:53:11 +01001256#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001257
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001258 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001259 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1262 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1265 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001266
1267 /*
1268 * Make sure Q coordinates are normalized
1269 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001270 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1271 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001272
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001273 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1274 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001275
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001276 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1277 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1278 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1279 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1280 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1281 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001282
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001283 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001284 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001285 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001286 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001287 {
1288 ret = ecp_double_jac( grp, R, P );
1289 goto cleanup;
1290 }
1291 else
1292 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001293 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001294 goto cleanup;
1295 }
1296 }
1297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001298 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1299 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1300 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1301 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1302 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1303 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1304 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1305 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1306 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1307 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1308 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1309 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001311 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1312 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1313 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001314
1315cleanup:
1316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1318 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001319
1320 return( ret );
1321}
1322
1323/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001324 * Randomize jacobian coordinates:
1325 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001326 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001327 *
1328 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001329 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001331 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1332{
1333 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001334 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001335 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001336 int count = 0;
1337
Janos Follathb0697532016-08-18 12:38:46 +01001338#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001339 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001340 {
Janos Follathc44ab972016-11-18 16:38:23 +00001341 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001342 }
Janos Follath372697b2016-10-28 16:53:11 +01001343#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001344
1345 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001346 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001347
1348 /* Generate l such that 1 < l < p */
1349 do
1350 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001351 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1354 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001355
1356 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001357 {
1358 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1359 goto cleanup;
1360 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001361 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001362 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001363
1364 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 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 +02001366
1367 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001368 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1369 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 +02001370
1371 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1373 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 +02001374
1375cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001376 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001377
1378 return( ret );
1379}
1380
1381/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001382 * Check and define parameters used by the comb method (see below for details)
1383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1385#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001386#endif
1387
1388/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001389#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001390
1391/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001392#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001393
1394/*
1395 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001396 *
1397 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001398 * modified version that provides resistance to SPA by avoiding zero
1399 * digits in the representation as in [3]. We modify the method further by
1400 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001401 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001402 *
1403 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1404 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1405 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001406 *
1407 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001408 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001409 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001410 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001411 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1412 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001413 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001414static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001415 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001416{
1417 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001418 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001419
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001420 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001421
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001422 /* First get the classical comb values (except for x_d = 0) */
1423 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001424 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001425 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001426
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001427 /* Now make sure x_1 .. x_d are odd */
1428 c = 0;
1429 for( i = 1; i <= d; i++ )
1430 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001431 /* Add carry and update it */
1432 cc = x[i] & c;
1433 x[i] = x[i] ^ c;
1434 c = cc;
1435
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001436 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001437 adjust = 1 - ( x[i] & 0x01 );
1438 c |= x[i] & ( x[i-1] * adjust );
1439 x[i] = x[i] ^ ( x[i-1] * adjust );
1440 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001441 }
1442}
1443
1444/*
1445 * Precompute points for the comb method
1446 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001447 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1448 * 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 +01001449 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001450 * T must be able to hold 2^{w - 1} elements
1451 *
1452 * 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 +01001453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001454static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1455 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001456 unsigned char w, size_t d )
1457{
1458 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001459 unsigned char i, k;
1460 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001461 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001462
1463 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001464 * Set T[0] = P and
1465 * 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 +01001466 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001467 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001468
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001469 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001470 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001471 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001472 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001474 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001476
1477 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001478 }
1479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001481
1482 /*
1483 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001484 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001485 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001486 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001487 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001488 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001489 j = i;
1490 while( j-- )
1491 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001493 TT[k++] = &T[i + j];
1494 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001495 }
1496
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001497 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001498
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001499cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001500
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001501 return( ret );
1502}
1503
1504/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001505 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001506 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001507static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1508 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001509 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001510{
1511 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001512 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001513
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001514 /* Ignore the "sign" bit and scale down */
1515 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001516
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001517 /* Read the whole table to thwart cache-based timing attacks */
1518 for( j = 0; j < t_len; j++ )
1519 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001520 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1521 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001522 }
1523
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001524 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001525 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001526
1527cleanup:
1528 return( ret );
1529}
1530
1531/*
1532 * Core multiplication algorithm for the (modified) comb method.
1533 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001534 *
1535 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001537static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1538 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001539 const unsigned char x[], size_t d,
1540 int (*f_rng)(void *, unsigned char *, size_t),
1541 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001542{
1543 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001545 size_t i;
1546
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001547 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001548
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001549 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001550 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001551 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1552 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001553#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001554 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001555#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001557
1558 while( i-- != 0 )
1559 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001560 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1561 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1562 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001563 }
1564
1565cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001567 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001568
1569 return( ret );
1570}
1571
1572/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001573 * Multiplication using the comb method,
1574 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001575 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001576static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1577 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001578 int (*f_rng)(void *, unsigned char *, size_t),
1579 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001580{
1581 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001582 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1583 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001584 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001585 mbedtls_ecp_point *T;
1586 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001588 mbedtls_mpi_init( &M );
1589 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001590
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001591 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001592 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1593 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001594
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001595 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001596 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001597 * 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 +01001598 * (see costs of the various parts, with 1S = 1M)
1599 */
1600 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001601
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001602 /*
1603 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001604 * Just adding one avoids upping the cost of the first mul too much,
1605 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1608 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1609 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001610 if( p_eq_g )
1611 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001612#else
1613 p_eq_g = 0;
1614#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001615
1616 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001617 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001618 * (The last test is useful only for very small curves in the test suite.)
1619 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001620 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1621 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001622 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001623 w = 2;
1624
1625 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001626 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001627 d = ( grp->nbits + w - 1 ) / w;
1628
1629 /*
1630 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001631 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001632 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001633 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001634
1635 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001636 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001637 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001638 if( T == NULL )
1639 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001640 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001641 goto cleanup;
1642 }
1643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001644 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001645
1646 if( p_eq_g )
1647 {
1648 grp->T = T;
1649 grp->T_size = pre_len;
1650 }
1651 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001652
1653 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001654 * Make sure M is odd (M = m or M = N - m, since N is odd)
1655 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001657 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1658 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1659 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1660 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001661
1662 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001663 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001664 */
1665 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001666 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 +01001667
1668 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001669 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001670 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001671 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001672
1673 /*
1674 * Knowledge of the jacobian coordinates may leak the last few bits of the
1675 * scalar [1], and since our MPI implementation isn't constant-flow,
1676 * inversion (used for coordinate normalization) may leak the full value
1677 * of its input via side-channels [2].
1678 *
1679 * [1] https://eprint.iacr.org/2003/191
1680 * [2] https://eprint.iacr.org/2020/055
1681 *
1682 * Avoid the leak by randomizing coordinates before we normalize them.
1683 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001684#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001685 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001686#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001687 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001689
1690cleanup:
1691
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001692 /* There are two cases where T is not stored in grp:
1693 * - P != G
1694 * - An intermediate operation failed before setting grp->T
1695 * In either case, T must be freed.
1696 */
1697 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001698 {
1699 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001700 mbedtls_ecp_point_free( &T[i] );
1701 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001702 }
1703
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001704 mbedtls_mpi_free( &M );
1705 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001706
1707 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001708 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001709
1710 return( ret );
1711}
1712
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001713#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001714
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001715#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001716/*
1717 * For Montgomery curves, we do all the internal arithmetic in projective
1718 * coordinates. Import/export of points uses only the x coordinates, which is
1719 * internaly represented as X / Z.
1720 *
1721 * For scalar multiplication, we'll use a Montgomery ladder.
1722 */
1723
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001724/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001725 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1726 * Cost: 1M + 1I
1727 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001728static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001729{
1730 int ret;
1731
Janos Follathb0697532016-08-18 12:38:46 +01001732#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001733 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001734 {
Janos Follathc44ab972016-11-18 16:38:23 +00001735 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001736 }
Janos Follath372697b2016-10-28 16:53:11 +01001737#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001739 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1740 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1741 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001742
1743cleanup:
1744 return( ret );
1745}
1746
1747/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001748 * Randomize projective x/z coordinates:
1749 * (X, Z) -> (l X, l Z) for random l
1750 * This is sort of the reverse operation of ecp_normalize_mxz().
1751 *
1752 * This countermeasure was first suggested in [2].
1753 * Cost: 2M
1754 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001755static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001756 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1757{
1758 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001759 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001760 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001761 int count = 0;
1762
Janos Follathb0697532016-08-18 12:38:46 +01001763#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001764 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001765 {
Janos Follathc44ab972016-11-18 16:38:23 +00001766 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001767 }
Janos Follath372697b2016-10-28 16:53:11 +01001768#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001769
1770 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001771 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001772
1773 /* Generate l such that 1 < l < p */
1774 do
1775 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001776 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001777
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1779 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001780
1781 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001782 {
1783 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1784 goto cleanup;
1785 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001786 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001787 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001788
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001789 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1790 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 +01001791
1792cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001793 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001794
1795 return( ret );
1796}
1797
1798/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001799 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1800 * for Montgomery curves in x/z coordinates.
1801 *
1802 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1803 * with
1804 * d = X1
1805 * P = (X2, Z2)
1806 * Q = (X3, Z3)
1807 * R = (X4, Z4)
1808 * S = (X5, Z5)
1809 * and eliminating temporary variables tO, ..., t4.
1810 *
1811 * Cost: 5M + 4S
1812 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001813static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1814 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1815 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1816 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001817{
1818 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001819 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001820
Janos Follathb0697532016-08-18 12:38:46 +01001821#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001822 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001823 {
Janos Follathc44ab972016-11-18 16:38:23 +00001824 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001825 }
Janos Follath372697b2016-10-28 16:53:11 +01001826#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1829 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1830 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001831
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1833 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1834 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1835 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1836 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1837 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1838 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1839 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1840 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1841 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1842 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1843 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1844 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1845 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1846 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1847 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1848 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1849 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 +01001850
1851cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001852 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1853 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1854 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001855
1856 return( ret );
1857}
1858
1859/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001860 * Multiplication with Montgomery ladder in x/z coordinates,
1861 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001862 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001863static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1864 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001865 int (*f_rng)(void *, unsigned char *, size_t),
1866 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001867{
1868 int ret;
1869 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001870 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 mbedtls_ecp_point RP;
1872 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001874 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001875
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001876 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001877 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1878 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001879
1880 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001881 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1882 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1883 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001884
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001885 /* RP.X might be sligtly larger than P, so reduce it */
1886 MOD_ADD( RP.X );
1887
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001888 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001889#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001890 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001891#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001892 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001893
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001894 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001895 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001896 while( i-- > 0 )
1897 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001898 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001899 /*
1900 * if (b) R = 2R + P else R = 2R,
1901 * which is:
1902 * if (b) double_add( RP, R, RP, R )
1903 * else double_add( R, RP, R, RP )
1904 * but using safe conditional swaps to avoid leaks
1905 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001906 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1907 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1908 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1909 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1910 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001911 }
1912
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001913 /*
1914 * Knowledge of the projective coordinates may leak the last few bits of the
1915 * scalar [1], and since our MPI implementation isn't constant-flow,
1916 * inversion (used for coordinate normalization) may leak the full value
1917 * of its input via side-channels [2].
1918 *
1919 * [1] https://eprint.iacr.org/2003/191
1920 * [2] https://eprint.iacr.org/2020/055
1921 *
1922 * Avoid the leak by randomizing coordinates before we normalize them.
1923 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001924#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001925 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001926#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001927 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1928
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001929 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001930
1931cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001932 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001933
1934 return( ret );
1935}
1936
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001937#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001938
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001939/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001940 * Multiplication R = m * P
1941 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001942int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1943 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001944 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1945{
Janos Follathb0697532016-08-18 12:38:46 +01001946 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001947#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1948 char is_grp_capable = 0;
1949#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001950#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1951 ecp_drbg_context drbg_ctx;
1952
1953 ecp_drbg_init( &drbg_ctx );
1954#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001955
1956 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001957 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1958 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001960 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1961 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001962 return( ret );
1963
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001964#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1965 if( f_rng == NULL )
1966 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02001967 const size_t m_len = ( grp->nbits + 7 ) / 8;
1968 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001969 f_rng = &ecp_drbg_random;
1970 p_rng = &drbg_ctx;
1971 }
1972#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
1973
Janos Follathc44ab972016-11-18 16:38:23 +00001974#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001975 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001976 {
Janos Follathc44ab972016-11-18 16:38:23 +00001977 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01001978 }
Janos Follathc44ab972016-11-18 16:38:23 +00001979#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001980
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001981#if defined(ECP_MONTGOMERY)
1982 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01001983 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00001984#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001985#if defined(ECP_SHORTWEIERSTRASS)
1986 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01001987 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001988#endif
Janos Follathb0697532016-08-18 12:38:46 +01001989
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001990#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1991cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00001992#endif
Janos Follathc44ab972016-11-18 16:38:23 +00001993#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001994 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01001995 {
Janos Follathc44ab972016-11-18 16:38:23 +00001996 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01001997 }
Janos Follathc44ab972016-11-18 16:38:23 +00001998#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001999
2000#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2001 ecp_drbg_free( &drbg_ctx );
2002#endif
2003
Janos Follathb0697532016-08-18 12:38:46 +01002004 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002005}
2006
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002007#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002008/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002009 * Check that an affine point is valid as a public key,
2010 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002011 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002012static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002013{
2014 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002015 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002016
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002017 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002018 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2019 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2020 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2021 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2022 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002024 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002025
2026 /*
2027 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002028 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002029 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002030 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2031 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002032
2033 /* Special case for A = -3 */
2034 if( grp->A.p == NULL )
2035 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002037 }
2038 else
2039 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002040 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002041 }
2042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2044 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002045
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002046 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2047 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002048
2049cleanup:
2050
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002051 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002052
2053 return( ret );
2054}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002055#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002056
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002057/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002058 * R = m * P with shortcuts for m == 1 and m == -1
2059 * NOT constant-time - ONLY for short Weierstrass!
2060 */
2061static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2062 mbedtls_ecp_point *R,
2063 const mbedtls_mpi *m,
2064 const mbedtls_ecp_point *P )
2065{
2066 int ret;
2067
2068 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2069 {
2070 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2071 }
2072 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2073 {
2074 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2075 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2076 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2077 }
2078 else
2079 {
2080 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2081 }
2082
2083cleanup:
2084 return( ret );
2085}
2086
2087/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002088 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002089 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002090 */
2091int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2092 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2093 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2094{
2095 int ret;
2096 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002097#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2098 char is_grp_capable = 0;
2099#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002100
2101 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2102 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2103
2104 mbedtls_ecp_point_init( &mP );
2105
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002106 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2107 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002108
Janos Follathc44ab972016-11-18 16:38:23 +00002109#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002110 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002111 {
Janos Follathc44ab972016-11-18 16:38:23 +00002112 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002113 }
Janos Follath430d3372016-11-03 14:25:37 +00002114
Janos Follathc44ab972016-11-18 16:38:23 +00002115#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002116 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2117 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2118
2119cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002120
Janos Follathc44ab972016-11-18 16:38:23 +00002121#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2122 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002123 {
Janos Follathc44ab972016-11-18 16:38:23 +00002124 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002125 }
Janos Follathb0697532016-08-18 12:38:46 +01002126
Janos Follathc44ab972016-11-18 16:38:23 +00002127#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002128 mbedtls_ecp_point_free( &mP );
2129
2130 return( ret );
2131}
2132
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002133
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002134#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002135/*
2136 * Check validity of a public key for Montgomery curves with x-only schemes
2137 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002138static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002139{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002140 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002141 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2142 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002143
2144 return( 0 );
2145}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002146#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002147
2148/*
2149 * Check that a point is valid as a public key
2150 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002152{
2153 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002154 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2155 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002156
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002157#if defined(ECP_MONTGOMERY)
2158 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002159 return( ecp_check_pubkey_mx( grp, pt ) );
2160#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002161#if defined(ECP_SHORTWEIERSTRASS)
2162 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002163 return( ecp_check_pubkey_sw( grp, pt ) );
2164#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002165 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002166}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002167
2168/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002169 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002171int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002172{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002173#if defined(ECP_MONTGOMERY)
2174 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002175 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002176 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002177 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2178 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2179 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002180 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002181 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002182 else
2183 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002184 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002185#endif /* ECP_MONTGOMERY */
2186#if defined(ECP_SHORTWEIERSTRASS)
2187 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002188 {
2189 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2191 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2192 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002193 else
2194 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002195 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002196#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002197
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002198 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002199}
2200
2201/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002202 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002203 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002204int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2205 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002206 int (*f_rng)(void *, unsigned char *, size_t),
2207 void *p_rng )
2208{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002209 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002210 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002211
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002212#if defined(ECP_MONTGOMERY)
2213 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002214 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002215 /* [M225] page 5 */
2216 size_t b;
2217
Janos Follath98e28a72016-05-31 14:03:54 +01002218 do {
2219 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2220 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002221
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002222 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002223 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002224 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002226 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002227 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002228
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002229 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002230 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2231 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2232 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002233 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002234#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002235
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002236#if defined(ECP_SHORTWEIERSTRASS)
2237 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002238 {
2239 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002240 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002241 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002242
2243 /*
2244 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2245 * - use the same byte ordering;
2246 * - keep the leftmost nbits bits of the generated octet string;
2247 * - try until result is in the desired range.
2248 * This also avoids any biais, which is especially important for ECDSA.
2249 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002250 do
2251 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002252 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002254
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002255 /*
2256 * Each try has at worst a probability 1/2 of failing (the msb has
2257 * a probability 1/2 of being 0, and then the result will be < N),
2258 * so after 30 tries failure probability is a most 2**(-30).
2259 *
2260 * For most curves, 1 try is enough with overwhelming probability,
2261 * since N starts with a lot of 1s in binary, but some curves
2262 * such as secp224k1 are actually very close to the worst case.
2263 */
2264 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002265 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002266
Janos Follathc3b376e2019-10-11 14:21:53 +01002267 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002268 if( ret != 0 )
2269 {
2270 goto cleanup;
2271 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002272 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002273 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002274 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002275#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002276
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002277cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002278 return( ret );
2279}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002280
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002281/*
2282 * Generate a keypair with configurable base point
2283 */
2284int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2285 const mbedtls_ecp_point *G,
2286 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2287 int (*f_rng)(void *, unsigned char *, size_t),
2288 void *p_rng )
2289{
2290 int ret;
2291
2292 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2293 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2294
2295cleanup:
2296 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002297}
2298
2299/*
2300 * Generate key pair, wrapper for conventional base point
2301 */
2302int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2303 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2304 int (*f_rng)(void *, unsigned char *, size_t),
2305 void *p_rng )
2306{
2307 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002308}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002309
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002310/*
2311 * Generate a keypair, prettier wrapper
2312 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002313int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002314 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2315{
2316 int ret;
2317
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002318 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002319 return( ret );
2320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002321 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002322}
2323
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002324/*
2325 * Check a public-private key pair
2326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002327int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002328{
2329 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_ecp_point Q;
2331 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002333 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002334 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002335 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2336 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2337 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002338 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002339 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002340 }
2341
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002342 mbedtls_ecp_point_init( &Q );
2343 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002344
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002345 /* mbedtls_ecp_mul() needs a non-const group... */
2346 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002347
2348 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002350
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002351 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2352 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2353 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002355 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002356 goto cleanup;
2357 }
2358
2359cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002360 mbedtls_ecp_point_free( &Q );
2361 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002362
2363 return( ret );
2364}
2365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002366#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002367
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002368#if defined(ECP_ONE_STEP_KDF)
2369/*
2370 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2371 * but unofficial ones can be found at:
2372 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2373 *
2374 * We only use the ones with empty fixedInfo, and for brevity's sake, only
2375 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
2376 * exactly one block, and with SHA-512 less than one block).
2377 */
2378#if defined(MBEDTLS_SHA512_C)
2379
2380static const uint8_t test_kdf_z[16] = {
2381 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
2382 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
2383};
2384static const uint8_t test_kdf_out[32] = {
2385 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
2386 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
2387 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
2388 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
2389};
2390
2391#elif defined(MBEDTLS_SHA256_C)
2392
2393static const uint8_t test_kdf_z[16] = {
2394 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
2395 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
2396};
2397static const uint8_t test_kdf_out[32] = {
2398 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
2399 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
2400 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
2401 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
2402};
2403
2404#elif defined(MBEDTLS_SHA1_C)
2405
2406static const uint8_t test_kdf_z[16] = {
2407 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
2408 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
2409};
2410static const uint8_t test_kdf_out[32] = {
2411 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
2412 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
2413 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
2414 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
2415};
2416
2417#else
2418#error "Need at least one of SHA-512, SHA-256 or SHA-1"
2419#endif
2420
2421static int ecp_kdf_self_test( void )
2422{
2423 int ret;
2424 ecp_drbg_context kdf_ctx;
2425 mbedtls_mpi scalar;
2426 uint8_t out[sizeof( test_kdf_out )];
2427
2428 ecp_drbg_init( &kdf_ctx );
2429 mbedtls_mpi_init( &scalar );
2430 memset( out, 0, sizeof( out ) );
2431
2432 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2433 test_kdf_z, sizeof( test_kdf_z ) ) );
2434
2435 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2436 &scalar, sizeof( test_kdf_z ) ) );
2437
2438 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2439
2440 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2441 ret = -1;
2442
2443cleanup:
2444 ecp_drbg_free( &kdf_ctx );
2445 mbedtls_mpi_free( &scalar );
2446
2447 return( ret );
2448}
2449#endif /* ECP_ONE_STEP_KDF */
2450
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002451/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002452 * Checkup routine
2453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002454int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002455{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002456 int ret;
2457 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002458 mbedtls_ecp_group grp;
2459 mbedtls_ecp_point R, P;
2460 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002461 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002462 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002463 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002464 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002465 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002466 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002467 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002468 "400000000000000000000000000000000000000000000000", /* one and zeros */
2469 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2470 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002471 };
2472
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473 mbedtls_ecp_group_init( &grp );
2474 mbedtls_ecp_point_init( &R );
2475 mbedtls_ecp_point_init( &P );
2476 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002477
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002478 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002479#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002480 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002481#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002482 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002483#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002484
2485 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002486 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002487
2488 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002489 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2490 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002491
2492 add_count = 0;
2493 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002494 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002495 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2496 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002497
2498 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2499 {
2500 add_c_prev = add_count;
2501 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002502 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002503 add_count = 0;
2504 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002505 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002506
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002507 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2508 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002509
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002510 if( add_count != add_c_prev ||
2511 dbl_count != dbl_c_prev ||
2512 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002513 {
2514 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002515 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002516
2517 ret = 1;
2518 goto cleanup;
2519 }
2520 }
2521
2522 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002523 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002524
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002525 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002527 /* We computed P = 2G last time, use it */
2528
2529 add_count = 0;
2530 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002531 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002532 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2533 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002534
2535 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2536 {
2537 add_c_prev = add_count;
2538 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002539 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002540 add_count = 0;
2541 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002542 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002544 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2545 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002546
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002547 if( add_count != add_c_prev ||
2548 dbl_count != dbl_c_prev ||
2549 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002550 {
2551 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002552 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002553
2554 ret = 1;
2555 goto cleanup;
2556 }
2557 }
2558
2559 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002560 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002561
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002562#if defined(ECP_ONE_STEP_KDF)
2563 if( verbose != 0 )
2564 mbedtls_printf( " ECP test #3 (internal KDF): " );
2565
2566 ret = ecp_kdf_self_test();
2567 if( ret != 0 )
2568 {
2569 if( verbose != 0 )
2570 mbedtls_printf( "failed\n" );
2571
2572 ret = 1;
2573 goto cleanup;
2574 }
2575
2576 if( verbose != 0 )
2577 mbedtls_printf( "passed\n" );
2578#endif /* ECP_ONE_STEP_KDF */
2579
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002580cleanup:
2581
2582 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002583 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002585 mbedtls_ecp_group_free( &grp );
2586 mbedtls_ecp_point_free( &R );
2587 mbedtls_ecp_point_free( &P );
2588 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002589
2590 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002591 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002592
2593 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002594}
2595
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002596#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002597
Janos Follathb0697532016-08-18 12:38:46 +01002598#endif /* !MBEDTLS_ECP_ALT */
2599
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002600#endif /* MBEDTLS_ECP_C */