blob: 6fdadf22ed051bc66e3690b58c14bdd7db9c4f86 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
Manuel Pégourié-Gonnard32b04c12013-12-02 15:49:09 +01002 * Elliptic curves over GF(p): generic functions
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010020 */
21
22/*
23 * References:
24 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +010026 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010027 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010028 * RFC 4492 for the related TLS structures and constants
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020029 *
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +020030 * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +010031 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020032 * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020033 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
34 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
35 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010036 *
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +020037 * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +010038 * render ECC resistant against Side Channel Attacks. IACR Cryptology
39 * ePrint Archive, 2004, vol. 2004, p. 342.
40 * <http://eprint.iacr.org/2004/342.pdf>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010041 */
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020045#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020047#endif
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010048
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020049#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010050
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/ecp.h"
Janos Follath430d3372016-11-03 14:25:37 +000052#include "mbedtls/threading.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020053
Rich Evans00ab4702015-02-06 13:43:58 +000054#include <string.h>
55
Janos Follathb0697532016-08-18 12:38:46 +010056#if !defined(MBEDTLS_ECP_ALT)
57
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000059#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020060#else
Rich Evans00ab4702015-02-06 13:43:58 +000061#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000062#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020064#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065#define mbedtls_free free
Paul Bakker6e339b52013-07-03 13:37:05 +020066#endif
67
Janos Follath47d28f02016-11-01 13:22:05 +000068#include "mbedtls/ecp_internal.h"
Janos Follathb0697532016-08-18 12:38:46 +010069
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020070#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020071#if defined(MBEDTLS_HMAC_DRBG_C)
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020072#include "mbedtls/hmac_drbg.h"
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +020073#elif defined(MBEDTLS_CTR_DRBG_C)
74#include "mbedtls/ctr_drbg.h"
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +020075#elif defined(MBEDTLS_SHA512_C)
76#include "mbedtls/sha512.h"
77#elif defined(MBEDTLS_SHA256_C)
78#include "mbedtls/sha256.h"
79#elif defined(MBEDTLS_SHA1_C)
80#include "mbedtls/sha1.h"
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020081#else
82#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
83#endif
84#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
85
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +010086#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
87 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +010088#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +020089#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +010090
Paul Bakker34617722014-06-13 17:20:13 +020091/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020093 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
94}
95
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010097/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +010098 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020099 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100100 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +0100101static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +0100102#endif
103
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200104#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
105/*
106 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200107 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200108 * that people will pass non-NULL RNG when they care about side-channels, but
109 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
110 * no opportunity for the user to do anything about it.
111 *
112 * The obvious strategies for addressing that include:
113 * - change those APIs so that they take RNG arguments;
114 * - require a global RNG to be available to all crypto modules.
115 *
116 * Unfortunately those would break compatibility. So what we do instead is
117 * have our own internal DRBG instance, seeded from the secret scalar.
118 *
119 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200120 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200121 */
122
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200123#if defined(MBEDTLS_HMAC_DRBG_C)
124
125/* DRBG context type */
126typedef mbedtls_hmac_drbg_context ecp_drbg_context;
127
128/* DRBG context init */
129static inline void ecp_drbg_init( ecp_drbg_context *ctx )
130{
131 mbedtls_hmac_drbg_init( ctx );
132}
133
134/* DRBG context free */
135static inline void ecp_drbg_free( ecp_drbg_context *ctx )
136{
137 mbedtls_hmac_drbg_free( ctx );
138}
139
140/* DRBG function */
141static inline int ecp_drbg_random( void *p_rng,
142 unsigned char *output, size_t output_len )
143{
144 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
145}
146
147/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200148static int ecp_drbg_seed( ecp_drbg_context *ctx,
149 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200150{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200151 int ret;
152 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200153 /* The list starts with strong hashes */
154 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
155 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
156
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200157 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
158 secret_bytes, secret_len ) );
159
160 ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
161
162cleanup:
163 mbedtls_zeroize( secret_bytes, secret_len );
164
165 return( ret );
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200166}
167
168#elif defined(MBEDTLS_CTR_DRBG_C)
169
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200170/* DRBG context type */
171typedef mbedtls_ctr_drbg_context ecp_drbg_context;
172
173/* DRBG context init */
174static inline void ecp_drbg_init( ecp_drbg_context *ctx )
175{
176 mbedtls_ctr_drbg_init( ctx );
177}
178
179/* DRBG context free */
180static inline void ecp_drbg_free( ecp_drbg_context *ctx )
181{
182 mbedtls_ctr_drbg_free( ctx );
183}
184
185/* DRBG function */
186static inline int ecp_drbg_random( void *p_rng,
187 unsigned char *output, size_t output_len )
188{
189 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
190}
191
192/*
193 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
194 * we need to pass an entropy function when seeding. So we use a dummy
195 * function for that, and pass the actual entropy as customisation string.
196 * (During seeding of CTR_DRBG the entropy input and customisation string are
197 * concatenated before being used to update the secret state.)
198 */
199static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
200{
201 (void) ctx;
202 memset( out, 0, len );
203 return( 0 );
204}
205
206/* DRBG context seeding */
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200207static int ecp_drbg_seed( ecp_drbg_context *ctx,
208 const mbedtls_mpi *secret, size_t secret_len )
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200209{
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200210 int ret;
211 unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200212
Manuel Pégourié-Gonnard601128e2020-06-17 10:12:43 +0200213 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
214 secret_bytes, secret_len ) );
215
216 ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
217 secret_bytes, secret_len );
218
219cleanup:
220 mbedtls_zeroize( secret_bytes, secret_len );
221
222 return( ret );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200223}
224
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200225#elif defined(MBEDTLS_SHA512_C) || \
226 defined(MBEDTLS_SHA256_C) || \
227 defined(MBEDTLS_SHA1_C)
228
229/* This will be used in the self-test function */
230#define ECP_ONE_STEP_KDF
231
232/*
233 * We need to expand secret data (the scalar) into a longer stream of bytes.
234 *
235 * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
236 * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
237 * convenience, this is not a full-fledged DRBG, but we don't need one here.)
238 *
239 * We need a basic hash abstraction layer to use whatever SHA is available.
240 */
241#if defined(MBEDTLS_SHA512_C)
242
243#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
244#define HASH_BLOCK_BYTES ( 512 / 8 )
245
246#elif defined(MBEDTLS_SHA256_C)
247
248#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
249#define HASH_BLOCK_BYTES ( 256 / 8 )
250
251#else // from a previous #if we know that SHA-1 is available if SHA-2 isn't
252
253#define HASH_FUNC mbedtls_sha1_ret
254#define HASH_BLOCK_BYTES ( 160 / 8 )
255
256#endif /* SHA512/SHA256/SHA1 abstraction */
257
258/*
259 * State consists of a 32-bit counter plus the secret value.
260 *
261 * We stored them concatenated in a single buffer as that's what will get
262 * passed to the hash function.
263 */
264typedef struct {
265 size_t total_len;
266 uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
267} ecp_drbg_context;
268
269static void ecp_drbg_init( ecp_drbg_context *ctx )
270{
271 memset( ctx, 0, sizeof( ecp_drbg_context ) );
272}
273
274static void ecp_drbg_free( ecp_drbg_context *ctx )
275{
276 mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) );
277}
278
279static int ecp_drbg_seed( ecp_drbg_context *ctx,
280 const mbedtls_mpi *secret, size_t secret_len )
281{
282 ctx->total_len = 4 + secret_len;
283 memset( ctx->buf, 0, 4);
284 return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
285}
286
287static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
288{
289 ecp_drbg_context *ctx = p_rng;
290 int ret;
291 size_t len_done = 0;
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200292 uint8_t tmp[HASH_BLOCK_BYTES];
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200293
294 while( len_done < output_len )
295 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200296 uint8_t use_len;
297
298 /* We don't need to draw more that 255 blocks, so don't bother with
299 * carry propagation and just return an error instead. */
300 ctx->buf[3] += 1;
301 if( ctx->buf[3] == 0 )
302 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
303
304 ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
305 if( ret != 0 )
306 return( ret );
307
308 if( output_len - len_done > HASH_BLOCK_BYTES )
309 use_len = HASH_BLOCK_BYTES;
310 else
311 use_len = output_len - len_done;
312
313 memcpy( output + len_done, tmp, use_len );
314 len_done += use_len;
315 }
316
Manuel Pégourié-Gonnard87459862020-06-17 12:40:57 +0200317 mbedtls_zeroize( tmp, sizeof( tmp ) );
318
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200319 return( 0 );
320}
321
322#else /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200323#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +0200324#endif /* DRBG/SHA modules */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200325#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
328 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
329 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
330 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
331 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
332 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
333 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
334 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
335 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
336 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
337 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200338#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100339#endif
340
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200341#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200342#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100343#endif
344
345/*
346 * Curve types: internal for now, might be exposed later
347 */
348typedef enum
349{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200350 ECP_TYPE_NONE = 0,
351 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
352 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100353} ecp_curve_type;
354
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100355/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200356 * List of supported curves:
357 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200358 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200359 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200360 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100361 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100362 * Curves are listed in order: largest curves first, and for a given size,
363 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200364 *
365 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200368{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
370 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200371#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
373 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100374#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
376 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200377#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
379 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100380#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
382 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200383#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
385 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100386#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200387#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
388 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100389#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
391 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200392#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
394 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100395#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200396#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
397 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100398#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
400 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100401#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200403};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100404
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200405#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
406 sizeof( ecp_supported_curves[0] )
407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200409
410/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200411 * List of supported curves and associated info
412 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200414{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200415 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200416}
417
418/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100419 * List of supported curves, group ID only
420 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100422{
423 static int init_done = 0;
424
425 if( ! init_done )
426 {
427 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 for( curve_info = mbedtls_ecp_curve_list();
431 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100432 curve_info++ )
433 {
434 ecp_supported_grp_id[i++] = curve_info->grp_id;
435 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100437
438 init_done = 1;
439 }
440
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200441 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100442}
443
444/*
445 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200446 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447const 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 +0200448{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200450
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 for( curve_info = mbedtls_ecp_curve_list();
452 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200453 curve_info++ )
454 {
455 if( curve_info->grp_id == grp_id )
456 return( curve_info );
457 }
458
459 return( NULL );
460}
461
462/*
463 * Get the curve info from the TLS identifier
464 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200466{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 for( curve_info = mbedtls_ecp_curve_list();
470 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200471 curve_info++ )
472 {
473 if( curve_info->tls_id == tls_id )
474 return( curve_info );
475 }
476
477 return( NULL );
478}
479
480/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100481 * Get the curve info from the name
482 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100484{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 for( curve_info = mbedtls_ecp_curve_list();
488 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100489 curve_info++ )
490 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200491 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100492 return( curve_info );
493 }
494
495 return( NULL );
496}
497
498/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100499 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100500 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200501static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100502{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100503 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200504 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100505
506 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200507 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100508 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200509 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100510}
511
512/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100513 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100514 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100516{
517 if( pt == NULL )
518 return;
519
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 mbedtls_mpi_init( &pt->X );
521 mbedtls_mpi_init( &pt->Y );
522 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100523}
524
525/*
526 * Initialize (the components of) a group
527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100529{
530 if( grp == NULL )
531 return;
532
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100534}
535
536/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200537 * Initialize (the components of) a key pair
538 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200540{
Paul Bakker66d5d072014-06-17 16:39:18 +0200541 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200542 return;
543
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 mbedtls_ecp_group_init( &key->grp );
545 mbedtls_mpi_init( &key->d );
546 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200547}
548
549/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100550 * Unallocate (the components of) a point
551 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100553{
554 if( pt == NULL )
555 return;
556
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557 mbedtls_mpi_free( &( pt->X ) );
558 mbedtls_mpi_free( &( pt->Y ) );
559 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100560}
561
562/*
563 * Unallocate (the components of) a group
564 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100566{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200567 size_t i;
568
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100569 if( grp == NULL )
570 return;
571
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100572 if( grp->h != 1 )
573 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 mbedtls_mpi_free( &grp->P );
575 mbedtls_mpi_free( &grp->A );
576 mbedtls_mpi_free( &grp->B );
577 mbedtls_ecp_point_free( &grp->G );
578 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100579 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200580
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200581 if( grp->T != NULL )
582 {
583 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200584 mbedtls_ecp_point_free( &grp->T[i] );
585 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200586 }
587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100589}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100590
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100591/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200592 * Unallocate (the components of) a key pair
593 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200595{
Paul Bakker66d5d072014-06-17 16:39:18 +0200596 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200597 return;
598
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 mbedtls_ecp_group_free( &key->grp );
600 mbedtls_mpi_free( &key->d );
601 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200602}
603
604/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200605 * Copy the contents of a point
606 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200608{
609 int ret;
610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
612 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
613 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200614
615cleanup:
616 return( ret );
617}
618
619/*
620 * Copy the contents of a group object
621 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200623{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200624 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200625}
626
627/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100628 * Set point to zero
629 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200630int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100631{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100632 int ret;
633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
635 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
636 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100637
638cleanup:
639 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100640}
641
642/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100643 * Tell if a point is zero
644 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100646{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100648}
649
650/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700651 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200652 */
653int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
654 const mbedtls_ecp_point *Q )
655{
656 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
657 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
658 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
659 {
660 return( 0 );
661 }
662
663 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
664}
665
666/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100667 * Import a non-zero point from ASCII strings
668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100670 const char *x, const char *y )
671{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100672 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100673
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
675 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
676 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100677
678cleanup:
679 return( ret );
680}
681
682/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100683 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100684 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100686 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100687 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100688{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200689 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100690 size_t plen;
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
693 format != MBEDTLS_ECP_PF_COMPRESSED )
694 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100695
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100696 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100697 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100698 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100700 {
701 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100703
704 buf[0] = 0x00;
705 *olen = 1;
706
707 return( 0 );
708 }
709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100713 {
714 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100715
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100716 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100718
719 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
721 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100722 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100724 {
725 *olen = plen + 1;
726
727 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100729
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
731 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100732 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100733
734cleanup:
735 return( ret );
736}
737
738/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100739 * Import a point from unsigned binary data (SEC1 2.3.4)
740 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100742 const unsigned char *buf, size_t ilen )
743{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100744 int ret;
745 size_t plen;
746
Paul Bakker82788fb2014-10-20 13:59:19 +0200747 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200749
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100750 if( buf[0] == 0x00 )
751 {
752 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100754 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100756 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100759
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100760 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100762
763 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200764 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100765
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200766 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
767 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
768 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100769
770cleanup:
771 return( ret );
772}
773
774/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100775 * Import a point from a TLS ECPoint record (RFC 4492)
776 * struct {
777 * opaque point <1..2^8-1>;
778 * } ECPoint;
779 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200780int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100781 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100782{
783 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100784 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100785
786 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200787 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100788 */
789 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200790 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100791
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100792 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100793 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200794 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100795
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100796 /*
797 * Save buffer start for read_binary and update buf
798 */
799 buf_start = *buf;
800 *buf += data_len;
801
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200802 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100803}
804
805/*
806 * Export a point as a TLS ECPoint record (RFC 4492)
807 * struct {
808 * opaque point <1..2^8-1>;
809 * } ECPoint;
810 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200811int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100812 int format, size_t *olen,
813 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100814{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100815 int ret;
816
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100817 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100818 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100819 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100820 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200821 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100822
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200823 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100824 olen, buf + 1, blen - 1) ) != 0 )
825 return( ret );
826
827 /*
828 * write length to the first byte and update total length
829 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200830 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100831 ++*olen;
832
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200833 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100834}
835
836/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100837 * Set a group from an ECParameters record (RFC 4492)
838 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200839int 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 +0100840{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200841 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100843
844 /*
845 * We expect at least three bytes (see below)
846 */
847 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200848 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100849
850 /*
851 * First byte is curve_type; only named_curve is handled
852 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200853 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
854 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100855
856 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100857 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100858 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200859 tls_id = *(*buf)++;
860 tls_id <<= 8;
861 tls_id |= *(*buf)++;
862
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200863 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
864 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200865
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200866 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100867}
868
869/*
870 * Write the ECParameters record corresponding to a group (RFC 4492)
871 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100873 unsigned char *buf, size_t blen )
874{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200875 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200876
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200877 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
878 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200879
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100880 /*
881 * We are going to write 3 bytes (see below)
882 */
883 *olen = 3;
884 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200885 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100886
887 /*
888 * First byte is curve_type, always named_curve
889 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200890 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100891
892 /*
893 * Next two bytes are the namedcurve value
894 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200895 buf[0] = curve_info->tls_id >> 8;
896 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100897
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200898 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100899}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100900
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200901/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200902 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
903 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200904 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200905 * 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 +0200906 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200907static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200908{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200909 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200910
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200911 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200912 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200913
914 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200915 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200916 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200917 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200918 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200919 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200920
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200922
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200923 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
925 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200926
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200927 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200928 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200929 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200930
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200931cleanup:
932 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200933}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200934
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100935/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100936 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100937 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100938 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 * 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 +0100940 * bring the result back to this range.
941 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100942 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100943 */
944
945/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 * 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 +0100947 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200948#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100949#define INC_MUL_COUNT mul_count++;
950#else
951#define INC_MUL_COUNT
952#endif
953
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100955 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100956
957/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200958 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200959 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100960 */
961#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200962 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
963 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100964
965/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200966 * 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 +0200967 * We known P, N and the result are positive, so sub_abs is correct, and
968 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100969 */
970#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200971 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
972 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100973
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200974#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100975/*
976 * For curves in short Weierstrass form, we do all the internal operations in
977 * Jacobian coordinates.
978 *
979 * For multiplication, we'll use a comb method with coutermeasueres against
980 * SPA, hence timing attacks.
981 */
982
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100983/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100984 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100985 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100986 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200987static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100988{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100989 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200990 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100991
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200992 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100993 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100994
Janos Follathb0697532016-08-18 12:38:46 +0100995#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000996 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100997 {
Janos Follathc44ab972016-11-18 16:38:23 +0000998 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +0100999 }
Janos Follath372697b2016-10-28 16:53:11 +01001000#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001001 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001002
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001003 /*
1004 * X = X / Z^2 mod p
1005 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001006 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
1007 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1008 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 +01001009
1010 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001011 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001012 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
1014 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 +01001015
1016 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001017 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001018 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001019 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001020
1021cleanup:
1022
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +01001024
1025 return( ret );
1026}
1027
1028/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001029 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001030 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001031 * (See for example Cohen's "A Course in Computational Algebraic Number
1032 * Theory", Algorithm 10.3.4.)
1033 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001034 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001035 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001036 *
1037 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001038 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
1040 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001041{
1042 int ret;
1043 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001044 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001045
1046 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001047 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001048
Janos Follathb0697532016-08-18 12:38:46 +01001049#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001050 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001051 {
Janos Follathc44ab972016-11-18 16:38:23 +00001052 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +01001053 }
1054#endif
1055
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001056 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001057 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001058
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001059 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001060
1061 /*
1062 * c[i] = Z_0 * ... * Z_i
1063 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001064 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001065 for( i = 1; i < t_len; i++ )
1066 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001067 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001068 MOD_MUL( c[i] );
1069 }
1070
1071 /*
1072 * u = 1 / (Z_0 * ... * Z_n) mod P
1073 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001075
1076 for( i = t_len - 1; ; i-- )
1077 {
1078 /*
1079 * Zi = 1 / Z_i mod p
1080 * u = 1 / (Z_0 * ... * Z_i) mod P
1081 */
1082 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001083 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001084 }
1085 else
1086 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001087 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1088 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001089 }
1090
1091 /*
1092 * proceed as in normalize()
1093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001094 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1095 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
1096 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
1097 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 +01001098
1099 /*
1100 * Post-precessing: reclaim some memory by shrinking coordinates
1101 * - not storing Z (always 1)
1102 * - shrinking other coordinates, but still keeping the same number of
1103 * limbs as P, as otherwise it will too likely be regrown too fast.
1104 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001105 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
1106 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
1107 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001108
1109 if( i == 0 )
1110 break;
1111 }
1112
1113cleanup:
1114
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001115 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001116 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001117 mbedtls_mpi_free( &c[i] );
1118 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001119
1120 return( ret );
1121}
1122
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001123/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001124 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1125 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001127static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1128 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001129 unsigned char inv )
1130{
1131 int ret;
1132 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001133 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001134
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001135 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001136
1137 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001138 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1139 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1140 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001141
1142cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001143 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001144
1145 return( ret );
1146}
1147
1148/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001149 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001150 *
Peter Dettmance661b22015-02-07 14:43:51 +07001151 * 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 +01001152 *
Peter Dettmance661b22015-02-07 14:43:51 +07001153 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1154 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1155 *
1156 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1157 *
1158 * Cost: 1D := 3M + 4S (A == 0)
1159 * 4M + 4S (A == -3)
1160 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001162static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1163 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001164{
1165 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001166 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001167
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001168#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001169 dbl_count++;
1170#endif
1171
Janos Follathb0697532016-08-18 12:38:46 +01001172#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001173 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001174 {
Janos Follathc44ab972016-11-18 16:38:23 +00001175 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001176 }
Janos Follath372697b2016-10-28 16:53:11 +01001177#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001178
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001179 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 +01001180
1181 /* Special case for A = -3 */
1182 if( grp->A.p == NULL )
1183 {
Peter Dettmance661b22015-02-07 14:43:51 +07001184 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001185 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1186 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1187 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1188 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1189 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001190 }
1191 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001192 {
Peter Dettmance661b22015-02-07 14:43:51 +07001193 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001194 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1195 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001196
1197 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001198 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001199 {
1200 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001201 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1202 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1203 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1204 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001205 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001206 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001207
Peter Dettmance661b22015-02-07 14:43:51 +07001208 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001209 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1211 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1212 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001213
Peter Dettmance661b22015-02-07 14:43:51 +07001214 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001215 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1216 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001217
1218 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001219 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1220 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1221 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001222
1223 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001224 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1225 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1226 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001227
1228 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001229 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1230 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001231
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001232 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1233 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1234 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001235
1236cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001237 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 +02001238
1239 return( ret );
1240}
1241
1242/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001243 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001244 *
1245 * The coordinates of Q must be normalized (= affine),
1246 * but those of P don't need to. R is not normalized.
1247 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001248 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001249 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001250 * - at each step, P, Q and R are multiples of the base point, the factor
1251 * being less than its order, so none of them is zero;
1252 * - Q is an odd multiple of the base point, P an even multiple,
1253 * due to the choice of precomputed points in the modified comb method.
1254 * So branches for these cases do not leak secret information.
1255 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001256 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1257 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001258 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001260static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1261 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001262{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001263 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001265
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001266#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001267 add_count++;
1268#endif
1269
Janos Follathb0697532016-08-18 12:38:46 +01001270#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001271 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001272 {
Janos Follathc44ab972016-11-18 16:38:23 +00001273 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001274 }
Janos Follath372697b2016-10-28 16:53:11 +01001275#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001276
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001277 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001278 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001280 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1281 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1284 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001285
1286 /*
1287 * Make sure Q coordinates are normalized
1288 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001289 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1290 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001292 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1293 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001295 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1296 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1297 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1298 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1299 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1300 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001301
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001302 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001303 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001304 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001305 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001306 {
1307 ret = ecp_double_jac( grp, R, P );
1308 goto cleanup;
1309 }
1310 else
1311 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001312 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001313 goto cleanup;
1314 }
1315 }
1316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001317 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1318 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1319 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1320 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1321 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1322 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1323 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1324 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1325 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1326 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1327 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1328 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001329
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001330 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1331 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1332 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001333
1334cleanup:
1335
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001336 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1337 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001338
1339 return( ret );
1340}
1341
1342/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001343 * Randomize jacobian coordinates:
1344 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001345 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001346 *
1347 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001348 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001349static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001350 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1351{
1352 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001354 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001355 int count = 0;
1356
Janos Follathb0697532016-08-18 12:38:46 +01001357#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001358 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001359 {
Janos Follathc44ab972016-11-18 16:38:23 +00001360 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001361 }
Janos Follath372697b2016-10-28 16:53:11 +01001362#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001363
1364 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001365 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001366
1367 /* Generate l such that 1 < l < p */
1368 do
1369 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001370 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001371
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1373 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001374
1375 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001376 {
1377 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1378 goto cleanup;
1379 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001380 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001381 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001382
1383 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001384 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 +02001385
1386 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001387 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1388 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 +02001389
1390 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1392 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 +02001393
1394cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001395 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001396
1397 return( ret );
1398}
1399
1400/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001401 * Check and define parameters used by the comb method (see below for details)
1402 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001403#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1404#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001405#endif
1406
1407/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001408#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001409
1410/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001411#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001412
1413/*
1414 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001415 *
1416 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001417 * modified version that provides resistance to SPA by avoiding zero
1418 * digits in the representation as in [3]. We modify the method further by
1419 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001420 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001421 *
1422 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1423 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1424 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001425 *
1426 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001427 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001428 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001429 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001430 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1431 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001432 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001433static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001434 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001435{
1436 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001437 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001438
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001439 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001440
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001441 /* First get the classical comb values (except for x_d = 0) */
1442 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001443 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001444 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001445
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001446 /* Now make sure x_1 .. x_d are odd */
1447 c = 0;
1448 for( i = 1; i <= d; i++ )
1449 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001450 /* Add carry and update it */
1451 cc = x[i] & c;
1452 x[i] = x[i] ^ c;
1453 c = cc;
1454
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001455 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001456 adjust = 1 - ( x[i] & 0x01 );
1457 c |= x[i] & ( x[i-1] * adjust );
1458 x[i] = x[i] ^ ( x[i-1] * adjust );
1459 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001460 }
1461}
1462
1463/*
1464 * Precompute points for the comb method
1465 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001466 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1467 * 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 +01001468 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001469 * T must be able to hold 2^{w - 1} elements
1470 *
1471 * 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 +01001472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001473static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1474 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001475 unsigned char w, size_t d )
1476{
1477 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001478 unsigned char i, k;
1479 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001480 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001481
1482 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001483 * Set T[0] = P and
1484 * 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 +01001485 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001486 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001487
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001488 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001489 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001490 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001491 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001492 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001493 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001494 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001495
1496 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001497 }
1498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001499 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001500
1501 /*
1502 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001503 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001504 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001505 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001506 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001507 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001508 j = i;
1509 while( j-- )
1510 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001511 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001512 TT[k++] = &T[i + j];
1513 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001514 }
1515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001516 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001517
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001518cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001519
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001520 return( ret );
1521}
1522
1523/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001524 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001526static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1527 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001528 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001529{
1530 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001531 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001532
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001533 /* Ignore the "sign" bit and scale down */
1534 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001535
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001536 /* Read the whole table to thwart cache-based timing attacks */
1537 for( j = 0; j < t_len; j++ )
1538 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001539 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1540 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001541 }
1542
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001543 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001544 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001545
1546cleanup:
1547 return( ret );
1548}
1549
1550/*
1551 * Core multiplication algorithm for the (modified) comb method.
1552 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001553 *
1554 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1557 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001558 const unsigned char x[], size_t d,
1559 int (*f_rng)(void *, unsigned char *, size_t),
1560 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001561{
1562 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001563 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001564 size_t i;
1565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001566 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001567
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001568 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001569 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1571 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001572#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001573 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001574#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001575 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001576
1577 while( i-- != 0 )
1578 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001579 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1580 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1581 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001582 }
1583
1584cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001585
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001586 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001587
1588 return( ret );
1589}
1590
1591/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001592 * Multiplication using the comb method,
1593 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001594 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001595static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1596 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001597 int (*f_rng)(void *, unsigned char *, size_t),
1598 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001599{
1600 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001601 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1602 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001603 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001604 mbedtls_ecp_point *T;
1605 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 mbedtls_mpi_init( &M );
1608 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001609
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001610 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001611 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1612 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001613
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001614 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001615 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001616 * 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 +01001617 * (see costs of the various parts, with 1S = 1M)
1618 */
1619 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001620
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001621 /*
1622 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001623 * Just adding one avoids upping the cost of the first mul too much,
1624 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001625 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001626#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1627 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1628 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001629 if( p_eq_g )
1630 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001631#else
1632 p_eq_g = 0;
1633#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001634
1635 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001636 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001637 * (The last test is useful only for very small curves in the test suite.)
1638 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001639 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1640 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001641 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001642 w = 2;
1643
1644 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001645 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001646 d = ( grp->nbits + w - 1 ) / w;
1647
1648 /*
1649 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001650 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001651 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001652 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001653
1654 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001655 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001656 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001657 if( T == NULL )
1658 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001659 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001660 goto cleanup;
1661 }
1662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001663 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001664
1665 if( p_eq_g )
1666 {
1667 grp->T = T;
1668 grp->T_size = pre_len;
1669 }
1670 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001671
1672 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001673 * Make sure M is odd (M = m or M = N - m, since N is odd)
1674 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001675 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001676 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1677 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1679 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001680
1681 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001682 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001683 */
1684 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001685 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 +01001686
1687 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001688 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001690 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001691
1692 /*
1693 * Knowledge of the jacobian coordinates may leak the last few bits of the
1694 * scalar [1], and since our MPI implementation isn't constant-flow,
1695 * inversion (used for coordinate normalization) may leak the full value
1696 * of its input via side-channels [2].
1697 *
1698 * [1] https://eprint.iacr.org/2003/191
1699 * [2] https://eprint.iacr.org/2020/055
1700 *
1701 * Avoid the leak by randomizing coordinates before we normalize them.
1702 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001703#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001704 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001705#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001706 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001707 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001708
1709cleanup:
1710
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001711 /* There are two cases where T is not stored in grp:
1712 * - P != G
1713 * - An intermediate operation failed before setting grp->T
1714 * In either case, T must be freed.
1715 */
1716 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001717 {
1718 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001719 mbedtls_ecp_point_free( &T[i] );
1720 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001721 }
1722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001723 mbedtls_mpi_free( &M );
1724 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001725
1726 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001728
1729 return( ret );
1730}
1731
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001732#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001733
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001734#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001735/*
1736 * For Montgomery curves, we do all the internal arithmetic in projective
1737 * coordinates. Import/export of points uses only the x coordinates, which is
1738 * internaly represented as X / Z.
1739 *
1740 * For scalar multiplication, we'll use a Montgomery ladder.
1741 */
1742
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001743/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001744 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1745 * Cost: 1M + 1I
1746 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001747static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001748{
1749 int ret;
1750
Janos Follathb0697532016-08-18 12:38:46 +01001751#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001752 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001753 {
Janos Follathc44ab972016-11-18 16:38:23 +00001754 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001755 }
Janos Follath372697b2016-10-28 16:53:11 +01001756#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001758 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1759 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1760 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001761
1762cleanup:
1763 return( ret );
1764}
1765
1766/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001767 * Randomize projective x/z coordinates:
1768 * (X, Z) -> (l X, l Z) for random l
1769 * This is sort of the reverse operation of ecp_normalize_mxz().
1770 *
1771 * This countermeasure was first suggested in [2].
1772 * Cost: 2M
1773 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001774static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001775 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1776{
1777 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001778 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001779 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001780 int count = 0;
1781
Janos Follathb0697532016-08-18 12:38:46 +01001782#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001783 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001784 {
Janos Follathc44ab972016-11-18 16:38:23 +00001785 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001786 }
Janos Follath372697b2016-10-28 16:53:11 +01001787#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001788
1789 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001790 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001791
1792 /* Generate l such that 1 < l < p */
1793 do
1794 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001795 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1798 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001799
1800 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001801 {
1802 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1803 goto cleanup;
1804 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001805 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001806 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001807
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001808 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1809 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 +01001810
1811cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001812 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001813
1814 return( ret );
1815}
1816
1817/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001818 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1819 * for Montgomery curves in x/z coordinates.
1820 *
1821 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1822 * with
1823 * d = X1
1824 * P = (X2, Z2)
1825 * Q = (X3, Z3)
1826 * R = (X4, Z4)
1827 * S = (X5, Z5)
1828 * and eliminating temporary variables tO, ..., t4.
1829 *
1830 * Cost: 5M + 4S
1831 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001832static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1833 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1834 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1835 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001836{
1837 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001838 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001839
Janos Follathb0697532016-08-18 12:38:46 +01001840#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001841 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001842 {
Janos Follathc44ab972016-11-18 16:38:23 +00001843 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001844 }
Janos Follath372697b2016-10-28 16:53:11 +01001845#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001847 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1848 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1849 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001850
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001851 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1852 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1853 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1854 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1855 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1856 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1857 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1858 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1859 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1860 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1861 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1862 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1863 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1864 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1865 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1866 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1867 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1868 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 +01001869
1870cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001871 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1872 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1873 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001874
1875 return( ret );
1876}
1877
1878/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001879 * Multiplication with Montgomery ladder in x/z coordinates,
1880 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001881 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001882static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1883 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001884 int (*f_rng)(void *, unsigned char *, size_t),
1885 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001886{
1887 int ret;
1888 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001889 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001890 mbedtls_ecp_point RP;
1891 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001892
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001893 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001894
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001895 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001896 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1897 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001898
1899 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001900 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1901 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1902 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001903
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001904 /* RP.X might be sligtly larger than P, so reduce it */
1905 MOD_ADD( RP.X );
1906
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001907 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001908#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001909 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001910#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001911 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001912
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001913 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001914 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001915 while( i-- > 0 )
1916 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001917 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001918 /*
1919 * if (b) R = 2R + P else R = 2R,
1920 * which is:
1921 * if (b) double_add( RP, R, RP, R )
1922 * else double_add( R, RP, R, RP )
1923 * but using safe conditional swaps to avoid leaks
1924 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001925 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1926 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1927 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1928 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001930 }
1931
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001932 /*
1933 * Knowledge of the projective coordinates may leak the last few bits of the
1934 * scalar [1], and since our MPI implementation isn't constant-flow,
1935 * inversion (used for coordinate normalization) may leak the full value
1936 * of its input via side-channels [2].
1937 *
1938 * [1] https://eprint.iacr.org/2003/191
1939 * [2] https://eprint.iacr.org/2020/055
1940 *
1941 * Avoid the leak by randomizing coordinates before we normalize them.
1942 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001943#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001944 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001945#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001946 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1947
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001948 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001949
1950cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001951 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001952
1953 return( ret );
1954}
1955
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001956#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001957
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001958/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001959 * Multiplication R = m * P
1960 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001961int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1962 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001963 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1964{
Janos Follathb0697532016-08-18 12:38:46 +01001965 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001966#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1967 char is_grp_capable = 0;
1968#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001969#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1970 ecp_drbg_context drbg_ctx;
1971
1972 ecp_drbg_init( &drbg_ctx );
1973#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001974
1975 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001976 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1977 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001978
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001979 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1980 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001981 return( ret );
1982
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001983#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1984 if( f_rng == NULL )
1985 {
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02001986 const size_t m_len = ( grp->nbits + 7 ) / 8;
1987 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001988 f_rng = &ecp_drbg_random;
1989 p_rng = &drbg_ctx;
1990 }
1991#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
1992
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 = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001995 {
Janos Follathc44ab972016-11-18 16:38:23 +00001996 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( 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
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002000#if defined(ECP_MONTGOMERY)
2001 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01002002 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00002003#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002004#if defined(ECP_SHORTWEIERSTRASS)
2005 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01002006 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002007#endif
Janos Follathb0697532016-08-18 12:38:46 +01002008
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002009#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2010cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00002011#endif
Janos Follathc44ab972016-11-18 16:38:23 +00002012#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002013 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002014 {
Janos Follathc44ab972016-11-18 16:38:23 +00002015 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002016 }
Janos Follathc44ab972016-11-18 16:38:23 +00002017#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02002018
2019#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
2020 ecp_drbg_free( &drbg_ctx );
2021#endif
2022
Janos Follathb0697532016-08-18 12:38:46 +01002023 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002024}
2025
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002026#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01002027/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002028 * Check that an affine point is valid as a public key,
2029 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002030 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002031static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002032{
2033 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002034 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002035
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002036 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002037 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
2038 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
2039 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
2040 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
2041 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002042
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002043 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002044
2045 /*
2046 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02002047 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002048 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
2050 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002051
2052 /* Special case for A = -3 */
2053 if( grp->A.p == NULL )
2054 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002055 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002056 }
2057 else
2058 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002059 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01002060 }
2061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002062 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
2063 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002064
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002065 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
2066 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002067
2068cleanup:
2069
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002070 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002071
2072 return( ret );
2073}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002074#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002075
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002076/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002077 * R = m * P with shortcuts for m == 1 and m == -1
2078 * NOT constant-time - ONLY for short Weierstrass!
2079 */
2080static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
2081 mbedtls_ecp_point *R,
2082 const mbedtls_mpi *m,
2083 const mbedtls_ecp_point *P )
2084{
2085 int ret;
2086
2087 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
2088 {
2089 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2090 }
2091 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
2092 {
2093 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
2094 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
2095 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
2096 }
2097 else
2098 {
2099 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
2100 }
2101
2102cleanup:
2103 return( ret );
2104}
2105
2106/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002107 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002108 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002109 */
2110int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
2111 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
2112 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
2113{
2114 int ret;
2115 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00002116#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2117 char is_grp_capable = 0;
2118#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002119
2120 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2121 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2122
2123 mbedtls_ecp_point_init( &mP );
2124
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002125 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2126 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002127
Janos Follathc44ab972016-11-18 16:38:23 +00002128#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002129 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002130 {
Janos Follathc44ab972016-11-18 16:38:23 +00002131 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002132 }
Janos Follath430d3372016-11-03 14:25:37 +00002133
Janos Follathc44ab972016-11-18 16:38:23 +00002134#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002135 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2136 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2137
2138cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002139
Janos Follathc44ab972016-11-18 16:38:23 +00002140#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2141 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002142 {
Janos Follathc44ab972016-11-18 16:38:23 +00002143 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002144 }
Janos Follathb0697532016-08-18 12:38:46 +01002145
Janos Follathc44ab972016-11-18 16:38:23 +00002146#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002147 mbedtls_ecp_point_free( &mP );
2148
2149 return( ret );
2150}
2151
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002152
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002153#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002154/*
2155 * Check validity of a public key for Montgomery curves with x-only schemes
2156 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002157static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002158{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002159 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002160 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2161 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002162
2163 return( 0 );
2164}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002165#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002166
2167/*
2168 * Check that a point is valid as a public key
2169 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002170int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002171{
2172 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002173 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2174 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002175
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002176#if defined(ECP_MONTGOMERY)
2177 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002178 return( ecp_check_pubkey_mx( grp, pt ) );
2179#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002180#if defined(ECP_SHORTWEIERSTRASS)
2181 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002182 return( ecp_check_pubkey_sw( grp, pt ) );
2183#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002184 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002185}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002186
2187/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002188 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002190int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002191{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002192#if defined(ECP_MONTGOMERY)
2193 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002194 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002195 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002196 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2197 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2198 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002199 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002200 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002201 else
2202 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002203 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002204#endif /* ECP_MONTGOMERY */
2205#if defined(ECP_SHORTWEIERSTRASS)
2206 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002207 {
2208 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002209 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2210 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2211 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002212 else
2213 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002214 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002215#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002216
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002217 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002218}
2219
2220/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002221 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002222 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002223int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2224 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002225 int (*f_rng)(void *, unsigned char *, size_t),
2226 void *p_rng )
2227{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002228 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002229 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002230
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002231#if defined(ECP_MONTGOMERY)
2232 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002233 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002234 /* [M225] page 5 */
2235 size_t b;
2236
Janos Follath98e28a72016-05-31 14:03:54 +01002237 do {
2238 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2239 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002240
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002241 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002242 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002243 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002244 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002245 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002246 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002247
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002248 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2250 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2251 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002252 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002253#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002254
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002255#if defined(ECP_SHORTWEIERSTRASS)
2256 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002257 {
2258 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002259 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002260 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002261
2262 /*
2263 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2264 * - use the same byte ordering;
2265 * - keep the leftmost nbits bits of the generated octet string;
2266 * - try until result is in the desired range.
2267 * This also avoids any biais, which is especially important for ECDSA.
2268 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002269 do
2270 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002271 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002272 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002273
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002274 /*
2275 * Each try has at worst a probability 1/2 of failing (the msb has
2276 * a probability 1/2 of being 0, and then the result will be < N),
2277 * so after 30 tries failure probability is a most 2**(-30).
2278 *
2279 * For most curves, 1 try is enough with overwhelming probability,
2280 * since N starts with a lot of 1s in binary, but some curves
2281 * such as secp224k1 are actually very close to the worst case.
2282 */
2283 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002284 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002285
Janos Follathc3b376e2019-10-11 14:21:53 +01002286 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002287 if( ret != 0 )
2288 {
2289 goto cleanup;
2290 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002291 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002292 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002293 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002294#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002295
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002296cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002297 return( ret );
2298}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002299
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002300/*
2301 * Generate a keypair with configurable base point
2302 */
2303int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2304 const mbedtls_ecp_point *G,
2305 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2306 int (*f_rng)(void *, unsigned char *, size_t),
2307 void *p_rng )
2308{
2309 int ret;
2310
2311 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2312 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2313
2314cleanup:
2315 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002316}
2317
2318/*
2319 * Generate key pair, wrapper for conventional base point
2320 */
2321int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2322 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2323 int (*f_rng)(void *, unsigned char *, size_t),
2324 void *p_rng )
2325{
2326 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002327}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002328
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002329/*
2330 * Generate a keypair, prettier wrapper
2331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002332int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002333 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2334{
2335 int ret;
2336
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002337 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002338 return( ret );
2339
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002340 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002341}
2342
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002343/*
2344 * Check a public-private key pair
2345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002346int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002347{
2348 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002349 mbedtls_ecp_point Q;
2350 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002351
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002352 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002353 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002354 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2355 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2356 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002357 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002358 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002359 }
2360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002361 mbedtls_ecp_point_init( &Q );
2362 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002363
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002364 /* mbedtls_ecp_mul() needs a non-const group... */
2365 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002366
2367 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002368 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002369
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002370 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2371 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2372 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002373 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002374 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002375 goto cleanup;
2376 }
2377
2378cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002379 mbedtls_ecp_point_free( &Q );
2380 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002381
2382 return( ret );
2383}
2384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002385#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002386
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002387#if defined(ECP_ONE_STEP_KDF)
2388/*
2389 * There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
2390 * but unofficial ones can be found at:
2391 * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
2392 *
2393 * We only use the ones with empty fixedInfo, and for brevity's sake, only
2394 * 32-bytes output (with SHA-1 that's more than one block, with SHA-256
2395 * exactly one block, and with SHA-512 less than one block).
2396 */
2397#if defined(MBEDTLS_SHA512_C)
2398
2399static const uint8_t test_kdf_z[16] = {
2400 0xeb, 0xf3, 0x19, 0x67, 0x1e, 0xac, 0xcc, 0x6f,
2401 0xc5, 0xc0, 0x5d, 0x95, 0x8d, 0x17, 0x15, 0x94,
2402};
2403static const uint8_t test_kdf_out[32] = {
2404 0xa9, 0x48, 0x85, 0x67, 0x54, 0x7c, 0x2a, 0x8e,
2405 0x9e, 0xd1, 0x67, 0x76, 0xe3, 0x1c, 0x03, 0x92,
2406 0x41, 0x77, 0x2a, 0x9e, 0xc7, 0xcc, 0xd7, 0x1f,
2407 0xda, 0x12, 0xe9, 0xba, 0xc9, 0xb2, 0x17, 0x24,
2408};
2409
2410#elif defined(MBEDTLS_SHA256_C)
2411
2412static const uint8_t test_kdf_z[16] = {
2413 0x0d, 0x5e, 0xc8, 0x9a, 0x68, 0xb1, 0xa7, 0xa0,
2414 0xdf, 0x95, 0x24, 0x54, 0x3f, 0x4d, 0x70, 0xef,
2415};
2416static const uint8_t test_kdf_out[32] = {
2417 0x77, 0xbc, 0x94, 0x9e, 0xa0, 0xd3, 0xdd, 0x5c,
2418 0x8e, 0xb7, 0xeb, 0x84, 0x05, 0x40, 0x60, 0xfa,
2419 0x96, 0x6e, 0x7e, 0xcd, 0x73, 0x9f, 0xa1, 0xe6,
2420 0x34, 0x3f, 0x6d, 0x82, 0x16, 0x22, 0xb4, 0x45,
2421};
2422
2423#elif defined(MBEDTLS_SHA1_C)
2424
2425static const uint8_t test_kdf_z[16] = {
2426 0x4e, 0x1e, 0x70, 0xc9, 0x88, 0x68, 0x19, 0xa3,
2427 0x1b, 0xc2, 0x9a, 0x53, 0x79, 0x11, 0xad, 0xd9,
2428};
2429static const uint8_t test_kdf_out[32] = {
2430 0xdd, 0xbf, 0xc4, 0x40, 0x44, 0x9a, 0xab, 0x41,
2431 0x31, 0xc6, 0xd8, 0xae, 0xc0, 0x8c, 0xe1, 0x49,
2432 0x6f, 0x27, 0x02, 0x24, 0x1d, 0x0e, 0x27, 0xcc,
2433 0x15, 0x5c, 0x5c, 0x7c, 0x3c, 0xda, 0x75, 0xb5,
2434};
2435
2436#else
2437#error "Need at least one of SHA-512, SHA-256 or SHA-1"
2438#endif
2439
2440static int ecp_kdf_self_test( void )
2441{
2442 int ret;
2443 ecp_drbg_context kdf_ctx;
2444 mbedtls_mpi scalar;
2445 uint8_t out[sizeof( test_kdf_out )];
2446
2447 ecp_drbg_init( &kdf_ctx );
2448 mbedtls_mpi_init( &scalar );
2449 memset( out, 0, sizeof( out ) );
2450
2451 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
2452 test_kdf_z, sizeof( test_kdf_z ) ) );
2453
2454 MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
2455 &scalar, sizeof( test_kdf_z ) ) );
2456
2457 MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
2458
2459 if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
2460 ret = -1;
2461
2462cleanup:
2463 ecp_drbg_free( &kdf_ctx );
2464 mbedtls_mpi_free( &scalar );
2465
2466 return( ret );
2467}
2468#endif /* ECP_ONE_STEP_KDF */
2469
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002470/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002471 * Checkup routine
2472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002473int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002474{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002475 int ret;
2476 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002477 mbedtls_ecp_group grp;
2478 mbedtls_ecp_point R, P;
2479 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002480 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002481 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002482 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002483 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002484 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002485 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002486 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002487 "400000000000000000000000000000000000000000000000", /* one and zeros */
2488 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2489 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002490 };
2491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002492 mbedtls_ecp_group_init( &grp );
2493 mbedtls_ecp_point_init( &R );
2494 mbedtls_ecp_point_init( &P );
2495 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002496
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002497 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002498#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002499 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002500#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002501 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002502#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002503
2504 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002505 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002506
2507 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002508 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2509 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002510
2511 add_count = 0;
2512 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002513 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002514 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2515 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002516
2517 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2518 {
2519 add_c_prev = add_count;
2520 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002521 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002522 add_count = 0;
2523 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002524 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002525
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002526 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2527 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002528
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002529 if( add_count != add_c_prev ||
2530 dbl_count != dbl_c_prev ||
2531 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002532 {
2533 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002534 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002535
2536 ret = 1;
2537 goto cleanup;
2538 }
2539 }
2540
2541 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002542 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002543
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002544 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002545 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002546 /* We computed P = 2G last time, use it */
2547
2548 add_count = 0;
2549 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002550 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002551 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2552 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002553
2554 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2555 {
2556 add_c_prev = add_count;
2557 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002558 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002559 add_count = 0;
2560 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002561 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002563 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2564 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002565
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002566 if( add_count != add_c_prev ||
2567 dbl_count != dbl_c_prev ||
2568 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002569 {
2570 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002571 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002572
2573 ret = 1;
2574 goto cleanup;
2575 }
2576 }
2577
2578 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002579 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002580
Manuel Pégourié-Gonnard6d614982020-06-16 12:51:42 +02002581#if defined(ECP_ONE_STEP_KDF)
2582 if( verbose != 0 )
2583 mbedtls_printf( " ECP test #3 (internal KDF): " );
2584
2585 ret = ecp_kdf_self_test();
2586 if( ret != 0 )
2587 {
2588 if( verbose != 0 )
2589 mbedtls_printf( "failed\n" );
2590
2591 ret = 1;
2592 goto cleanup;
2593 }
2594
2595 if( verbose != 0 )
2596 mbedtls_printf( "passed\n" );
2597#endif /* ECP_ONE_STEP_KDF */
2598
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002599cleanup:
2600
2601 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002602 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002603
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002604 mbedtls_ecp_group_free( &grp );
2605 mbedtls_ecp_point_free( &R );
2606 mbedtls_ecp_point_free( &P );
2607 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002608
2609 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002610 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002611
2612 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002613}
2614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002615#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002616
Janos Follathb0697532016-08-18 12:38:46 +01002617#endif /* !MBEDTLS_ECP_ALT */
2618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002619#endif /* MBEDTLS_ECP_C */