blob: 8c3379c45193c5a01bec25a5e45f920baa47b78a [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é-Gonnard75036a02020-05-22 12:12:36 +020075#else
76#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
77#endif
78#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
79
Manuel Pégourié-Gonnard0223ab92015-10-05 11:40:01 +010080#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
81 !defined(inline) && !defined(__cplusplus)
Paul Bakker6a6087e2013-10-28 18:53:08 +010082#define inline __inline
Manuel Pégourié-Gonnard20af64d2015-07-07 18:33:39 +020083#endif
Paul Bakker6a6087e2013-10-28 18:53:08 +010084
Paul Bakker34617722014-06-13 17:20:13 +020085/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020087 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
88}
89
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010091/*
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +010092 * Counts of point addition and doubling, and field multiplications.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020093 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010094 */
Manuel Pégourié-Gonnard43863ee2013-12-01 16:51:27 +010095static unsigned long add_count, dbl_count, mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010096#endif
97
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +020098#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
99/*
100 * Currently ecp_mul() takes a RNG function as an argument, used for
Manuel Pégourié-Gonnard99bf33f2020-06-10 09:18:25 +0200101 * side-channel protection, but it can be NULL. The initial reasoning was
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200102 * that people will pass non-NULL RNG when they care about side-channels, but
103 * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
104 * no opportunity for the user to do anything about it.
105 *
106 * The obvious strategies for addressing that include:
107 * - change those APIs so that they take RNG arguments;
108 * - require a global RNG to be available to all crypto modules.
109 *
110 * Unfortunately those would break compatibility. So what we do instead is
111 * have our own internal DRBG instance, seeded from the secret scalar.
112 *
113 * The following is a light-weight abstraction layer for doing that with
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200114 * HMAC_DRBG (first choice) or CTR_DRBG.
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200115 */
116
Manuel Pégourié-Gonnarde2828c22020-06-04 12:32:14 +0200117#if defined(MBEDTLS_HMAC_DRBG_C)
118
119/* DRBG context type */
120typedef mbedtls_hmac_drbg_context ecp_drbg_context;
121
122/* DRBG context init */
123static inline void ecp_drbg_init( ecp_drbg_context *ctx )
124{
125 mbedtls_hmac_drbg_init( ctx );
126}
127
128/* DRBG context free */
129static inline void ecp_drbg_free( ecp_drbg_context *ctx )
130{
131 mbedtls_hmac_drbg_free( ctx );
132}
133
134/* DRBG function */
135static inline int ecp_drbg_random( void *p_rng,
136 unsigned char *output, size_t output_len )
137{
138 return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
139}
140
141/* DRBG context seeding */
142static int ecp_drbg_seed( ecp_drbg_context *ctx, const mbedtls_mpi *secret )
143{
144 const unsigned char *secret_p = (const unsigned char *) secret->p;
145 const size_t secret_size = secret->n * sizeof( mbedtls_mpi_uint );
146
147 /* The list starts with strong hashes */
148 const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
149 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
150
151 return( mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_p, secret_size ) );
152}
153
154#elif defined(MBEDTLS_CTR_DRBG_C)
155
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200156/* DRBG context type */
157typedef mbedtls_ctr_drbg_context ecp_drbg_context;
158
159/* DRBG context init */
160static inline void ecp_drbg_init( ecp_drbg_context *ctx )
161{
162 mbedtls_ctr_drbg_init( ctx );
163}
164
165/* DRBG context free */
166static inline void ecp_drbg_free( ecp_drbg_context *ctx )
167{
168 mbedtls_ctr_drbg_free( ctx );
169}
170
171/* DRBG function */
172static inline int ecp_drbg_random( void *p_rng,
173 unsigned char *output, size_t output_len )
174{
175 return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
176}
177
178/*
179 * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
180 * we need to pass an entropy function when seeding. So we use a dummy
181 * function for that, and pass the actual entropy as customisation string.
182 * (During seeding of CTR_DRBG the entropy input and customisation string are
183 * concatenated before being used to update the secret state.)
184 */
185static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
186{
187 (void) ctx;
188 memset( out, 0, len );
189 return( 0 );
190}
191
192/* DRBG context seeding */
193static int ecp_drbg_seed( ecp_drbg_context *ctx, const mbedtls_mpi *secret )
194{
195 const unsigned char *secret_p = (const unsigned char *) secret->p;
196 const size_t secret_size = secret->n * sizeof( mbedtls_mpi_uint );
197
198 return( mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
199 secret_p, secret_size ) );
200}
201
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +0200202#else
203#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
204#endif /* DRBG modules */
205#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
208 defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
209 defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
210 defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
211 defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
212 defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
213 defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
214 defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \
215 defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
216 defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
217 defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200218#define ECP_SHORTWEIERSTRASS
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100219#endif
220
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +0200221#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200222#define ECP_MONTGOMERY
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100223#endif
224
225/*
226 * Curve types: internal for now, might be exposed later
227 */
228typedef enum
229{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200230 ECP_TYPE_NONE = 0,
231 ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
232 ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100233} ecp_curve_type;
234
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100235/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200236 * List of supported curves:
237 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200238 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200239 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200240 * - readable name
Gergely Budaie40c4692014-01-22 11:22:20 +0100241 *
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100242 * Curves are listed in order: largest curves first, and for a given size,
243 * fastest curves first. This provides the default order for the SSL module.
Manuel Pégourié-Gonnard88db5da2015-06-15 14:34:59 +0200244 *
245 * Reminder: update profiles in x509_crt.c when adding a new curves!
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200246 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247static const mbedtls_ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200248{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
250 { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200251#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
253 { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100254#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
256 { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200257#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200258#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
259 { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100260#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
262 { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200263#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
265 { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100266#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
268 { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
Gergely Budaie40c4692014-01-22 11:22:20 +0100269#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
271 { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200272#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
274 { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100275#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
277 { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100278#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
280 { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" },
Manuel Pégourié-Gonnard9bcff392014-01-10 18:26:48 +0100281#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200282 { MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200283};
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100284
Manuel Pégourié-Gonnardba782bb2014-07-08 13:31:34 +0200285#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \
286 sizeof( ecp_supported_curves[0] )
287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES];
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200289
290/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200291 * List of supported curves and associated info
292 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void )
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200294{
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200295 return( ecp_supported_curves );
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200296}
297
298/*
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100299 * List of supported curves, group ID only
300 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void )
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100302{
303 static int init_done = 0;
304
305 if( ! init_done )
306 {
307 size_t i = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 for( curve_info = mbedtls_ecp_curve_list();
311 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100312 curve_info++ )
313 {
314 ecp_supported_grp_id[i++] = curve_info->grp_id;
315 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100317
318 init_done = 1;
319 }
320
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200321 return( ecp_supported_grp_id );
Manuel Pégourié-Gonnardac719412014-02-04 14:48:50 +0100322}
323
324/*
325 * Get the curve info for the internal identifier
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200326 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327const 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 +0200328{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 for( curve_info = mbedtls_ecp_curve_list();
332 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200333 curve_info++ )
334 {
335 if( curve_info->grp_id == grp_id )
336 return( curve_info );
337 }
338
339 return( NULL );
340}
341
342/*
343 * Get the curve info from the TLS identifier
344 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200345const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200346{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200347 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200348
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 for( curve_info = mbedtls_ecp_curve_list();
350 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200351 curve_info++ )
352 {
353 if( curve_info->tls_id == tls_id )
354 return( curve_info );
355 }
356
357 return( NULL );
358}
359
360/*
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100361 * Get the curve info from the name
362 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100364{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 for( curve_info = mbedtls_ecp_curve_list();
368 curve_info->grp_id != MBEDTLS_ECP_DP_NONE;
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100369 curve_info++ )
370 {
Manuel Pégourié-Gonnardcb46fd82015-05-28 17:06:07 +0200371 if( strcmp( curve_info->name, name ) == 0 )
Manuel Pégourié-Gonnard0267e3d2013-11-30 15:10:14 +0100372 return( curve_info );
373 }
374
375 return( NULL );
376}
377
378/*
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100379 * Get the type of a curve
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100380 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100382{
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100383 if( grp->G.X.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200384 return( ECP_TYPE_NONE );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100385
386 if( grp->G.Y.p == NULL )
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200387 return( ECP_TYPE_MONTGOMERY );
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100388 else
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200389 return( ECP_TYPE_SHORT_WEIERSTRASS );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +0100390}
391
392/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100393 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100394 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395void mbedtls_ecp_point_init( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100396{
397 if( pt == NULL )
398 return;
399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 mbedtls_mpi_init( &pt->X );
401 mbedtls_mpi_init( &pt->Y );
402 mbedtls_mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100403}
404
405/*
406 * Initialize (the components of) a group
407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408void mbedtls_ecp_group_init( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100409{
410 if( grp == NULL )
411 return;
412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 memset( grp, 0, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100414}
415
416/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200417 * Initialize (the components of) a key pair
418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200420{
Paul Bakker66d5d072014-06-17 16:39:18 +0200421 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200422 return;
423
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 mbedtls_ecp_group_init( &key->grp );
425 mbedtls_mpi_init( &key->d );
426 mbedtls_ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200427}
428
429/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100430 * Unallocate (the components of) a point
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432void mbedtls_ecp_point_free( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100433{
434 if( pt == NULL )
435 return;
436
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 mbedtls_mpi_free( &( pt->X ) );
438 mbedtls_mpi_free( &( pt->Y ) );
439 mbedtls_mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100440}
441
442/*
443 * Unallocate (the components of) a group
444 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445void mbedtls_ecp_group_free( mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100446{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200447 size_t i;
448
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100449 if( grp == NULL )
450 return;
451
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100452 if( grp->h != 1 )
453 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 mbedtls_mpi_free( &grp->P );
455 mbedtls_mpi_free( &grp->A );
456 mbedtls_mpi_free( &grp->B );
457 mbedtls_ecp_point_free( &grp->G );
458 mbedtls_mpi_free( &grp->N );
Manuel Pégourié-Gonnard1f82b042013-12-06 12:51:50 +0100459 }
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200460
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200461 if( grp->T != NULL )
462 {
463 for( i = 0; i < grp->T_size; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 mbedtls_ecp_point_free( &grp->T[i] );
465 mbedtls_free( grp->T );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200466 }
467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100469}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100470
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100471/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200472 * Unallocate (the components of) a key pair
473 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200475{
Paul Bakker66d5d072014-06-17 16:39:18 +0200476 if( key == NULL )
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200477 return;
478
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 mbedtls_ecp_group_free( &key->grp );
480 mbedtls_mpi_free( &key->d );
481 mbedtls_ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200482}
483
484/*
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200485 * Copy the contents of a point
486 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200488{
489 int ret;
490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) );
492 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) );
493 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200494
495cleanup:
496 return( ret );
497}
498
499/*
500 * Copy the contents of a group object
501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200503{
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200504 return mbedtls_ecp_group_load( dst, src->id );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200505}
506
507/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100508 * Set point to zero
509 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100511{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100512 int ret;
513
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200514 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
515 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) );
516 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100517
518cleanup:
519 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100520}
521
522/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100523 * Tell if a point is zero
524 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100526{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100528}
529
530/*
Brian J Murraye02c9052018-10-22 16:40:49 -0700531 * Compare two points lazily
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200532 */
533int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
534 const mbedtls_ecp_point *Q )
535{
536 if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
537 mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
538 mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
539 {
540 return( 0 );
541 }
542
543 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
544}
545
546/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100547 * Import a non-zero point from ASCII strings
548 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100550 const char *x, const char *y )
551{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100552 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) );
555 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) );
556 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100557
558cleanup:
559 return( ret );
560}
561
562/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100563 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100564 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200565int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100566 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100567 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100568{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200569 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100570 size_t plen;
571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572 if( format != MBEDTLS_ECP_PF_UNCOMPRESSED &&
573 format != MBEDTLS_ECP_PF_COMPRESSED )
574 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100575
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100576 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100577 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100578 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100580 {
581 if( buflen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100583
584 buf[0] = 0x00;
585 *olen = 1;
586
587 return( 0 );
588 }
589
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100591
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 if( format == MBEDTLS_ECP_PF_UNCOMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100593 {
594 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100595
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100596 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100598
599 buf[0] = 0x04;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200600 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
601 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100602 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200603 else if( format == MBEDTLS_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100604 {
605 *olen = plen + 1;
606
607 if( buflen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100609
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 );
611 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100612 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100613
614cleanup:
615 return( ret );
616}
617
618/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100619 * Import a point from unsigned binary data (SEC1 2.3.4)
620 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100622 const unsigned char *buf, size_t ilen )
623{
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100624 int ret;
625 size_t plen;
626
Paul Bakker82788fb2014-10-20 13:59:19 +0200627 if( ilen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200629
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100630 if( buf[0] == 0x00 )
631 {
632 if( ilen == 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 return( mbedtls_ecp_set_zero( pt ) );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100634 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc042cf02014-03-26 14:12:20 +0100636 }
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 plen = mbedtls_mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100639
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100640 if( buf[0] != 0x04 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard5246ee52014-03-19 16:18:38 +0100642
643 if( ilen != 2 * plen + 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
647 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
648 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100649
650cleanup:
651 return( ret );
652}
653
654/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100655 * Import a point from a TLS ECPoint record (RFC 4492)
656 * struct {
657 * opaque point <1..2^8-1>;
658 * } ECPoint;
659 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100661 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100662{
663 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100664 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100665
666 /*
Manuel Pégourié-Gonnard67dbe1e2014-07-08 13:09:24 +0200667 * We must have at least two bytes (1 for length, at least one for data)
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100668 */
669 if( buf_len < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100671
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100672 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100673 if( data_len < 1 || data_len > buf_len - 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100675
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100676 /*
677 * Save buffer start for read_binary and update buf
678 */
679 buf_start = *buf;
680 *buf += data_len;
681
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100683}
684
685/*
686 * Export a point as a TLS ECPoint record (RFC 4492)
687 * struct {
688 * opaque point <1..2^8-1>;
689 * } ECPoint;
690 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100692 int format, size_t *olen,
693 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100694{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100695 int ret;
696
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100697 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100698 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100699 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100700 if( blen < 1 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703 if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100704 olen, buf + 1, blen - 1) ) != 0 )
705 return( ret );
706
707 /*
708 * write length to the first byte and update total length
709 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200710 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100711 ++*olen;
712
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200713 return( 0 );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100714}
715
716/*
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100717 * Set a group from an ECParameters record (RFC 4492)
718 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719int 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 +0100720{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200721 uint16_t tls_id;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100723
724 /*
725 * We expect at least three bytes (see below)
726 */
727 if( len < 3 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100729
730 /*
731 * First byte is curve_type; only named_curve is handled
732 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733 if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
734 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100735
736 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100737 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100738 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200739 tls_id = *(*buf)++;
740 tls_id <<= 8;
741 tls_id |= *(*buf)++;
742
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
744 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200745
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200746 return mbedtls_ecp_group_load( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100747}
748
749/*
750 * Write the ECParameters record corresponding to a group (RFC 4492)
751 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100753 unsigned char *buf, size_t blen )
754{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 const mbedtls_ecp_curve_info *curve_info;
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
758 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200759
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100760 /*
761 * We are going to write 3 bytes (see below)
762 */
763 *olen = 3;
764 if( blen < *olen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765 return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100766
767 /*
768 * First byte is curve_type, always named_curve
769 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200770 *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100771
772 /*
773 * Next two bytes are the namedcurve value
774 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200775 buf[0] = curve_info->tls_id >> 8;
776 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100777
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200778 return( 0 );
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100779}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100780
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200781/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200782 * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi.
783 * See the documentation of struct mbedtls_ecp_group.
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200784 *
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200785 * 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 +0200786 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200788{
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200789 int ret;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200790
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200791 if( grp->modp == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200792 return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200793
794 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200795 if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +0200796 mbedtls_mpi_bitlen( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200797 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200798 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200799 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200800
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200801 MBEDTLS_MPI_CHK( grp->modp( N ) );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200802
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200803 /* N->s < 0 is a much faster test, which fails only if N is 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200804 while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 )
805 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200806
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807 while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 )
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200808 /* we known P, N and the result are positive */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200809 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) );
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200810
Manuel Pégourié-Gonnardcae6f3e2013-10-23 20:19:57 +0200811cleanup:
812 return( ret );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200813}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200814
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100815/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100816 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100817 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100818 * In order to guarantee that, we need to ensure that operands of
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200819 * 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 +0100820 * bring the result back to this range.
821 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100822 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100823 */
824
825/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200826 * 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 +0100827 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200828#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100829#define INC_MUL_COUNT mul_count++;
830#else
831#define INC_MUL_COUNT
832#endif
833
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200834#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +0100835 while( 0 )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100836
837/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200838 * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi
Manuel Pégourié-Gonnardc9e387c2013-10-17 17:15:35 +0200839 * N->s < 0 is a very fast test, which fails only if N is 0
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100840 */
841#define MOD_SUB( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200842 while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \
843 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100844
845/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200846 * 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 +0200847 * We known P, N and the result are positive, so sub_abs is correct, and
848 * a bit faster.
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100849 */
850#define MOD_ADD( N ) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200851 while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
852 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100853
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +0200854#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +0100855/*
856 * For curves in short Weierstrass form, we do all the internal operations in
857 * Jacobian coordinates.
858 *
859 * For multiplication, we'll use a comb method with coutermeasueres against
860 * SPA, hence timing attacks.
861 */
862
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100863/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100864 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100865 * Cost: 1N := 1I + 3M + 1S
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100866 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100868{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100869 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200870 mbedtls_mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872 if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100873 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100874
Janos Follathb0697532016-08-18 12:38:46 +0100875#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000876 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100877 {
Janos Follathc44ab972016-11-18 16:38:23 +0000878 return mbedtls_internal_ecp_normalize_jac( grp, pt );
Janos Follathb0697532016-08-18 12:38:46 +0100879 }
Janos Follath372697b2016-10-28 16:53:11 +0100880#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200881 mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100882
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100883 /*
884 * X = X / Z^2 mod p
885 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200886 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
887 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
888 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 +0100889
890 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100891 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100892 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200893 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
894 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 +0100895
896 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100897 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100898 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200899 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100900
901cleanup:
902
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200903 mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100904
905 return( ret );
906}
907
908/*
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +0100909 * Normalize jacobian coordinates of an array of (pointers to) points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +0100910 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100911 * (See for example Cohen's "A Course in Computational Algebraic Number
912 * Theory", Algorithm 10.3.4.)
913 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200914 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +0100915 * This should never happen, see choice of w in ecp_mul_comb().
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +0100916 *
917 * Cost: 1N(t) := 1I + (6t - 3)M + 1S
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100918 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200919static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
920 mbedtls_ecp_point *T[], size_t t_len )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100921{
922 int ret;
923 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200924 mbedtls_mpi *c, u, Zi, ZZi;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100925
926 if( t_len < 2 )
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +0100927 return( ecp_normalize_jac( grp, *T ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100928
Janos Follathb0697532016-08-18 12:38:46 +0100929#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +0000930 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +0100931 {
Janos Follathc44ab972016-11-18 16:38:23 +0000932 return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len);
Janos Follathb0697532016-08-18 12:38:46 +0100933 }
934#endif
935
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200936 if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200937 return( MBEDTLS_ERR_ECP_ALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100938
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200939 mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100940
941 /*
942 * c[i] = Z_0 * ... * Z_i
943 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200944 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100945 for( i = 1; i < t_len; i++ )
946 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200947 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100948 MOD_MUL( c[i] );
949 }
950
951 /*
952 * u = 1 / (Z_0 * ... * Z_n) mod P
953 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100955
956 for( i = t_len - 1; ; i-- )
957 {
958 /*
959 * Zi = 1 / Z_i mod p
960 * u = 1 / (Z_0 * ... * Z_i) mod P
961 */
962 if( i == 0 ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200963 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100964 }
965 else
966 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
968 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100969 }
970
971 /*
972 * proceed as in normalize()
973 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200974 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
975 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X );
976 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y );
977 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 +0100978
979 /*
980 * Post-precessing: reclaim some memory by shrinking coordinates
981 * - not storing Z (always 1)
982 * - shrinking other coordinates, but still keeping the same number of
983 * limbs as P, as otherwise it will too likely be regrown too fast.
984 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200985 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) );
986 MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) );
987 mbedtls_mpi_free( &T[i]->Z );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100988
989 if( i == 0 )
990 break;
991 }
992
993cleanup:
994
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200995 mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100996 for( i = 0; i < t_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200997 mbedtls_mpi_free( &c[i] );
998 mbedtls_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100999
1000 return( ret );
1001}
1002
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001003/*
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001004 * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak.
1005 * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid
1006 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
1008 mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001009 unsigned char inv )
1010{
1011 int ret;
1012 unsigned char nonzero;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 mbedtls_mpi mQY;
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001014
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 mbedtls_mpi_init( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001016
1017 /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) );
1019 nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0;
1020 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001021
1022cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001023 mbedtls_mpi_free( &mQY );
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001024
1025 return( ret );
1026}
1027
1028/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001029 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001030 *
Peter Dettmance661b22015-02-07 14:43:51 +07001031 * 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 +01001032 *
Peter Dettmance661b22015-02-07 14:43:51 +07001033 * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR
1034 * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring.
1035 *
1036 * Standard optimizations are applied when curve parameter A is one of { 0, -3 }.
1037 *
1038 * Cost: 1D := 3M + 4S (A == 0)
1039 * 4M + 4S (A == -3)
1040 * 3M + 6S + 1a otherwise
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001041 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001042static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1043 const mbedtls_ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001044{
1045 int ret;
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001046 mbedtls_mpi M, S, T, U;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001047
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001048#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001049 dbl_count++;
1050#endif
1051
Janos Follathb0697532016-08-18 12:38:46 +01001052#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001053 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001054 {
Janos Follathc44ab972016-11-18 16:38:23 +00001055 return mbedtls_internal_ecp_double_jac( grp, R, P );
Janos Follathb0697532016-08-18 12:38:46 +01001056 }
Janos Follath372697b2016-10-28 16:53:11 +01001057#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001058
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001059 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 +01001060
1061 /* Special case for A = -3 */
1062 if( grp->A.p == NULL )
1063 {
Peter Dettmance661b22015-02-07 14:43:51 +07001064 /* M = 3(X + Z^2)(X - Z^2) */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001065 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1066 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T );
1067 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U );
1068 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S );
1069 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001070 }
1071 else
Peter Vaskovica676acf2014-08-06 00:48:39 +02001072 {
Peter Dettmance661b22015-02-07 14:43:51 +07001073 /* M = 3.X^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001074 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S );
1075 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001076
1077 /* Optimize away for "koblitz" curves with A = 0 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001078 if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 )
Peter Dettmance661b22015-02-07 14:43:51 +07001079 {
1080 /* M += A.Z^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001081 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S );
1082 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T );
1083 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S );
1084 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M );
Peter Dettmance661b22015-02-07 14:43:51 +07001085 }
Peter Vaskovica676acf2014-08-06 00:48:39 +02001086 }
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001087
Peter Dettmance661b22015-02-07 14:43:51 +07001088 /* S = 4.X.Y^2 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001089 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T );
1090 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T );
1091 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S );
1092 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001093
Peter Dettmance661b22015-02-07 14:43:51 +07001094 /* U = 8.Y^4 */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001095 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U );
1096 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001097
1098 /* T = M^2 - 2.S */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001099 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T );
1100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
1101 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T );
Peter Dettmance661b22015-02-07 14:43:51 +07001102
1103 /* S = M(S - T) - U */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001104 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S );
1105 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S );
1106 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S );
Peter Dettmance661b22015-02-07 14:43:51 +07001107
1108 /* U = 2.Y.Z */
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001109 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U );
1110 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U );
Peter Dettmance661b22015-02-07 14:43:51 +07001111
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001112 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) );
1113 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) );
1114 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001115
1116cleanup:
Manuel Pégourié-Gonnard2088ba62015-05-12 10:36:26 +02001117 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 +02001118
1119 return( ret );
1120}
1121
1122/*
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001123 * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22)
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001124 *
1125 * The coordinates of Q must be normalized (= affine),
1126 * but those of P don't need to. R is not normalized.
1127 *
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001128 * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q.
Manuel Pégourié-Gonnard7a949d32013-12-05 10:26:01 +01001129 * None of these cases can happen as intermediate step in ecp_mul_comb():
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001130 * - at each step, P, Q and R are multiples of the base point, the factor
1131 * being less than its order, so none of them is zero;
1132 * - Q is an odd multiple of the base point, P an even multiple,
1133 * due to the choice of precomputed points in the modified comb method.
1134 * So branches for these cases do not leak secret information.
1135 *
Manuel Pégourié-Gonnard72c172a2013-12-30 16:04:55 +01001136 * We accept Q->Z being unset (saving memory in tables) as meaning 1.
1137 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001138 * Cost: 1A := 8M + 3S
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001140static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1141 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001142{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001143 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001144 mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001146#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001147 add_count++;
1148#endif
1149
Janos Follathb0697532016-08-18 12:38:46 +01001150#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001151 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001152 {
Janos Follathc44ab972016-11-18 16:38:23 +00001153 return mbedtls_internal_ecp_add_mixed( grp, R, P, Q );
Janos Follathb0697532016-08-18 12:38:46 +01001154 }
Janos Follath372697b2016-10-28 16:53:11 +01001155#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001156
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001157 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001158 * Trivial cases: P == 0 or Q == 0 (case 1)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001160 if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 )
1161 return( mbedtls_ecp_copy( R, Q ) );
Manuel Pégourié-Gonnard469a2092013-11-21 18:20:43 +01001162
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001163 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 )
1164 return( mbedtls_ecp_copy( R, P ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001165
1166 /*
1167 * Make sure Q coordinates are normalized
1168 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001169 if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 )
1170 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001172 mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 );
1173 mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001175 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1176 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1177 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1178 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
1179 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1180 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001181
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001182 /* Special cases (2) and (3) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001183 if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001184 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001185 if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 )
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001186 {
1187 ret = ecp_double_jac( grp, R, P );
1188 goto cleanup;
1189 }
1190 else
1191 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001192 ret = mbedtls_ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001193 goto cleanup;
1194 }
1195 }
1196
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001197 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1198 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1199 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1200 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1201 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1202 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1203 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1204 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1206 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1207 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1208 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001209
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001210 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) );
1211 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) );
1212 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001213
1214cleanup:
1215
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001216 mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 );
1217 mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001218
1219 return( ret );
1220}
1221
1222/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001223 * Randomize jacobian coordinates:
1224 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
Manuel Pégourié-Gonnard3c0b4ea2013-12-02 19:44:41 +01001225 * This is sort of the reverse operation of ecp_normalize_jac().
Manuel Pégourié-Gonnard44aab792013-11-21 10:53:59 +01001226 *
1227 * This countermeasure was first suggested in [2].
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001229static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001230 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1231{
1232 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001233 mbedtls_mpi l, ll;
Janos Follathb0697532016-08-18 12:38:46 +01001234 size_t p_size;
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001235 int count = 0;
1236
Janos Follathb0697532016-08-18 12:38:46 +01001237#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001238 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001239 {
Janos Follathc44ab972016-11-18 16:38:23 +00001240 return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001241 }
Janos Follath372697b2016-10-28 16:53:11 +01001242#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001243
1244 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001245 mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001246
1247 /* Generate l such that 1 < l < p */
1248 do
1249 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001250 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001252 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1253 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001254
1255 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001256 {
1257 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1258 goto cleanup;
1259 }
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001260 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001261 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001262
1263 /* Z = l * Z */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001264 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 +02001265
1266 /* X = l^2 * X */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001267 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1268 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 +02001269
1270 /* Y = l^3 * Y */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001271 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1272 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 +02001273
1274cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001275 mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001276
1277 return( ret );
1278}
1279
1280/*
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001281 * Check and define parameters used by the comb method (see below for details)
1282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001283#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7
1284#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds"
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001285#endif
1286
1287/* d = ceil( n / w ) */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001288#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001289
1290/* number of precomputed points */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001291#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) )
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001292
1293/*
1294 * Compute the representation of m that will be used with our comb method.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001295 *
1296 * The basic comb method is described in GECC 3.44 for example. We use a
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001297 * modified version that provides resistance to SPA by avoiding zero
1298 * digits in the representation as in [3]. We modify the method further by
1299 * requiring that all K_i be odd, which has the small cost that our
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001300 * representation uses one more K_i, due to carries.
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001301 *
1302 * Also, for the sake of compactness, only the seven low-order bits of x[i]
1303 * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in
1304 * the paper): it is set if and only if if s_i == -1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001305 *
1306 * Calling conventions:
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001307 * - x is an array of size d + 1
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001308 * - w is the size, ie number of teeth, of the comb, and must be between
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001309 * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE)
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001310 * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d
1311 * (the result will be incorrect if these assumptions are not satisfied)
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001312 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001313static void ecp_comb_fixed( unsigned char x[], size_t d,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001314 unsigned char w, const mbedtls_mpi *m )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001315{
1316 size_t i, j;
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001317 unsigned char c, cc, adjust;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001318
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001319 memset( x, 0, d+1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001320
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001321 /* First get the classical comb values (except for x_d = 0) */
1322 for( i = 0; i < d; i++ )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001323 for( j = 0; j < w; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001324 x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001325
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001326 /* Now make sure x_1 .. x_d are odd */
1327 c = 0;
1328 for( i = 1; i <= d; i++ )
1329 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001330 /* Add carry and update it */
1331 cc = x[i] & c;
1332 x[i] = x[i] ^ c;
1333 c = cc;
1334
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001335 /* Adjust if needed, avoiding branches */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001336 adjust = 1 - ( x[i] & 0x01 );
1337 c |= x[i] & ( x[i-1] * adjust );
1338 x[i] = x[i] ^ ( x[i-1] * adjust );
1339 x[i-1] |= adjust << 7;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001340 }
1341}
1342
1343/*
1344 * Precompute points for the comb method
1345 *
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001346 * If i = i_{w-1} ... i_1 is the binary representation of i, then
1347 * 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 +01001348 *
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001349 * T must be able to hold 2^{w - 1} elements
1350 *
1351 * 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 +01001352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001353static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
1354 mbedtls_ecp_point T[], const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001355 unsigned char w, size_t d )
1356{
1357 int ret;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001358 unsigned char i, k;
1359 size_t j;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001360 mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1];
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001361
1362 /*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001363 * Set T[0] = P and
1364 * 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 +01001365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001366 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001367
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001368 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001369 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001370 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001371 cur = T + i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001372 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001373 for( j = 0; j < d; j++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001374 MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001375
1376 TT[k++] = cur;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001377 }
1378
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001379 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001380
1381 /*
1382 * Compute the remaining ones using the minimal number of additions
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001383 * Be careful to update T[2^l] only after using it!
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001384 */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001385 k = 0;
Paul Bakker66d5d072014-06-17 16:39:18 +02001386 for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001387 {
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001388 j = i;
1389 while( j-- )
1390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001391 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) );
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001392 TT[k++] = &T[i + j];
1393 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001394 }
1395
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001396 MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) );
Manuel Pégourié-Gonnarde2820122013-11-21 10:08:50 +01001397
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001398cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001399
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001400 return( ret );
1401}
1402
1403/*
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001404 * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ]
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001405 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001406static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1407 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001408 unsigned char i )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001409{
1410 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001411 unsigned char ii, j;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001412
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001413 /* Ignore the "sign" bit and scale down */
1414 ii = ( i & 0x7Fu ) >> 1;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001415
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001416 /* Read the whole table to thwart cache-based timing attacks */
1417 for( j = 0; j < t_len; j++ )
1418 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001419 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) );
1420 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) );
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001421 }
1422
Manuel Pégourié-Gonnard01fca5e2013-11-21 17:47:12 +01001423 /* Safely invert result if i is "negative" */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001424 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001425
1426cleanup:
1427 return( ret );
1428}
1429
1430/*
1431 * Core multiplication algorithm for the (modified) comb method.
1432 * This part is actually common with the basic comb method (GECC 3.44)
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001433 *
1434 * Cost: d A + d D + 1 R
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001436static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1437 const mbedtls_ecp_point T[], unsigned char t_len,
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001438 const unsigned char x[], size_t d,
1439 int (*f_rng)(void *, unsigned char *, size_t),
1440 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001441{
1442 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001443 mbedtls_ecp_point Txi;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001444 size_t i;
1445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001446 mbedtls_ecp_point_init( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001447
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001448 /* Start with a non-zero point and randomize its coordinates */
Manuel Pégourié-Gonnard101a39f2013-11-20 14:47:19 +01001449 i = d;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001450 MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) );
1451 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001452#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard70c14372013-11-20 20:07:26 +01001453 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001454#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001455 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001456
1457 while( i-- != 0 )
1458 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001459 MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) );
1460 MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) );
1461 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001462 }
1463
1464cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01001465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001466 mbedtls_ecp_point_free( &Txi );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001467
1468 return( ret );
1469}
1470
1471/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001472 * Multiplication using the comb method,
1473 * for curves in short Weierstrass form
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001475static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1476 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001477 int (*f_rng)(void *, unsigned char *, size_t),
1478 void *p_rng )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001479{
1480 int ret;
Manuel Pégourié-Gonnardd7283502013-11-21 20:00:38 +01001481 unsigned char w, m_is_odd, p_eq_g, pre_len, i;
1482 size_t d;
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001483 unsigned char k[COMB_MAX_D + 1];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001484 mbedtls_ecp_point *T;
1485 mbedtls_mpi M, mm;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001487 mbedtls_mpi_init( &M );
1488 mbedtls_mpi_init( &mm );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001489
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001490 /* we need N to be odd to trnaform m in an odd number, check now */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001491 if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 )
1492 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001493
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001494 /*
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001495 * Minimize the number of multiplications, that is minimize
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001496 * 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 +01001497 * (see costs of the various parts, with 1S = 1M)
1498 */
1499 w = grp->nbits >= 384 ? 5 : 4;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001500
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001501 /*
1502 * If P == G, pre-compute a bit more, since this may be re-used later.
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001503 * Just adding one avoids upping the cost of the first mul too much,
1504 * and the memory cost too.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001505 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001506#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
1507 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1508 mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001509 if( p_eq_g )
1510 w++;
Manuel Pégourié-Gonnard9e4191c2013-12-30 18:41:16 +01001511#else
1512 p_eq_g = 0;
1513#endif
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001514
1515 /*
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001516 * Make sure w is within bounds.
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001517 * (The last test is useful only for very small curves in the test suite.)
1518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001519 if( w > MBEDTLS_ECP_WINDOW_SIZE )
1520 w = MBEDTLS_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard36daa132013-11-21 18:33:36 +01001521 if( w >= grp->nbits )
Manuel Pégourié-Gonnard04a02252013-11-20 22:57:38 +01001522 w = 2;
1523
1524 /* Other sizes that depend on w */
Manuel Pégourié-Gonnardc30200e2013-11-20 18:39:55 +01001525 pre_len = 1U << ( w - 1 );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001526 d = ( grp->nbits + w - 1 ) / w;
1527
1528 /*
1529 * Prepare precomputed points: if P == G we want to
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001530 * use grp->T if already initialized, or initialize it.
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001531 */
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001532 T = p_eq_g ? grp->T : NULL;
Manuel Pégourié-Gonnardedc1a1f2013-11-21 09:50:00 +01001533
1534 if( T == NULL )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001535 {
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +02001536 T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001537 if( T == NULL )
1538 {
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +02001539 ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001540 goto cleanup;
1541 }
1542
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001543 MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001544
1545 if( p_eq_g )
1546 {
1547 grp->T = T;
1548 grp->T_size = pre_len;
1549 }
1550 }
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001551
1552 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001553 * Make sure M is odd (M = m or M = N - m, since N is odd)
1554 * using the fact that m * P = - (N - m) * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001555 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001556 m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 );
1557 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) );
1558 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) );
1559 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001560
1561 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001562 * Go for comb multiplication, R = M * P
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001563 */
1564 ecp_comb_fixed( k, d, w, &M );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001565 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 +01001566
1567 /*
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001568 * Now get m * P from M * P and normalize it
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001569 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001570 MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) );
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001571
1572 /*
1573 * Knowledge of the jacobian coordinates may leak the last few bits of the
1574 * scalar [1], and since our MPI implementation isn't constant-flow,
1575 * inversion (used for coordinate normalization) may leak the full value
1576 * of its input via side-channels [2].
1577 *
1578 * [1] https://eprint.iacr.org/2003/191
1579 * [2] https://eprint.iacr.org/2020/055
1580 *
1581 * Avoid the leak by randomizing coordinates before we normalize them.
1582 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001583#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001584 if( f_rng != 0 )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001585#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001586 MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001587 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001588
1589cleanup:
1590
Angus Grattoncb7a5b02017-09-06 15:07:17 +10001591 /* There are two cases where T is not stored in grp:
1592 * - P != G
1593 * - An intermediate operation failed before setting grp->T
1594 * In either case, T must be freed.
1595 */
1596 if( T != NULL && T != grp->T )
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001597 {
1598 for( i = 0; i < pre_len; i++ )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001599 mbedtls_ecp_point_free( &T[i] );
1600 mbedtls_free( T );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001601 }
1602
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001603 mbedtls_mpi_free( &M );
1604 mbedtls_mpi_free( &mm );
Manuel Pégourié-Gonnardaade42f2013-11-21 19:19:54 +01001605
1606 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001607 mbedtls_ecp_point_free( R );
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001608
1609 return( ret );
1610}
1611
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001612#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001613
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001614#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001615/*
1616 * For Montgomery curves, we do all the internal arithmetic in projective
1617 * coordinates. Import/export of points uses only the x coordinates, which is
1618 * internaly represented as X / Z.
1619 *
1620 * For scalar multiplication, we'll use a Montgomery ladder.
1621 */
1622
Manuel Pégourié-Gonnardd1c1ba92013-11-16 15:50:12 +01001623/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001624 * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1
1625 * Cost: 1M + 1I
1626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001627static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001628{
1629 int ret;
1630
Janos Follathb0697532016-08-18 12:38:46 +01001631#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001632 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001633 {
Janos Follathc44ab972016-11-18 16:38:23 +00001634 return mbedtls_internal_ecp_normalize_mxz( grp, P );
Janos Follathb0697532016-08-18 12:38:46 +01001635 }
Janos Follath372697b2016-10-28 16:53:11 +01001636#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001638 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) );
1639 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X );
1640 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001641
1642cleanup:
1643 return( ret );
1644}
1645
1646/*
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001647 * Randomize projective x/z coordinates:
1648 * (X, Z) -> (l X, l Z) for random l
1649 * This is sort of the reverse operation of ecp_normalize_mxz().
1650 *
1651 * This countermeasure was first suggested in [2].
1652 * Cost: 2M
1653 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001654static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001655 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1656{
1657 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001658 mbedtls_mpi l;
Janos Follathb0697532016-08-18 12:38:46 +01001659 size_t p_size;
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001660 int count = 0;
1661
Janos Follathb0697532016-08-18 12:38:46 +01001662#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001663 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001664 {
Janos Follathc44ab972016-11-18 16:38:23 +00001665 return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng );
Janos Follathb0697532016-08-18 12:38:46 +01001666 }
Janos Follath372697b2016-10-28 16:53:11 +01001667#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001668
1669 p_size = ( grp->pbits + 7 ) / 8;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001670 mbedtls_mpi_init( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001671
1672 /* Generate l such that 1 < l < p */
1673 do
1674 {
Ron Eldor7269fee2017-01-12 14:50:50 +02001675 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001676
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001677 while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1678 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001679
1680 if( count++ > 10 )
Jonas86c5c612020-05-08 16:57:18 +09001681 {
1682 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
1683 goto cleanup;
1684 }
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001685 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001686 while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001688 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X );
1689 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 +01001690
1691cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001692 mbedtls_mpi_free( &l );
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001693
1694 return( ret );
1695}
1696
1697/*
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001698 * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q),
1699 * for Montgomery curves in x/z coordinates.
1700 *
1701 * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3
1702 * with
1703 * d = X1
1704 * P = (X2, Z2)
1705 * Q = (X3, Z3)
1706 * R = (X4, Z4)
1707 * S = (X5, Z5)
1708 * and eliminating temporary variables tO, ..., t4.
1709 *
1710 * Cost: 5M + 4S
1711 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001712static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
1713 mbedtls_ecp_point *R, mbedtls_ecp_point *S,
1714 const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
1715 const mbedtls_mpi *d )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001716{
1717 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001718 mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001719
Janos Follathb0697532016-08-18 12:38:46 +01001720#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001721 if ( mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001722 {
Janos Follathc44ab972016-11-18 16:38:23 +00001723 return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d );
Janos Follathb0697532016-08-18 12:38:46 +01001724 }
Janos Follath372697b2016-10-28 16:53:11 +01001725#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
Janos Follathb0697532016-08-18 12:38:46 +01001726
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001727 mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B );
1728 mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C );
1729 mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001731 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A );
1732 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA );
1733 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B );
1734 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB );
1735 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E );
1736 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C );
1737 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D );
1738 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA );
1739 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB );
1740 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X );
1741 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X );
1742 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z );
1743 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z );
1744 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z );
1745 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X );
1746 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z );
1747 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z );
1748 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 +01001749
1750cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001751 mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B );
1752 mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C );
1753 mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001754
1755 return( ret );
1756}
1757
1758/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001759 * Multiplication with Montgomery ladder in x/z coordinates,
1760 * for curves in Montgomery form
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001761 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001762static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1763 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001764 int (*f_rng)(void *, unsigned char *, size_t),
1765 void *p_rng )
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001766{
1767 int ret;
1768 size_t i;
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001769 unsigned char b;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001770 mbedtls_ecp_point RP;
1771 mbedtls_mpi PX;
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001772
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001773 mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001774
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001775 /* Save PX and read from P before writing to R, in case P == R */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001776 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
1777 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001778
1779 /* Set R to zero in modified x/z coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001780 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) );
1781 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
1782 mbedtls_mpi_free( &R->Y );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001783
Manuel Pégourié-Gonnard93f41db2013-12-05 10:48:42 +01001784 /* RP.X might be sligtly larger than P, so reduce it */
1785 MOD_ADD( RP.X );
1786
Manuel Pégourié-Gonnard3afa07f2013-12-03 13:28:21 +01001787 /* Randomize coordinates of the starting point */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001788#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard357ff652013-12-04 18:39:17 +01001789 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001790#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001791 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001792
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001793 /* Loop invariant: R = result so far, RP = R + P */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02001794 i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001795 while( i-- > 0 )
1796 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001797 b = mbedtls_mpi_get_bit( m, i );
Manuel Pégourié-Gonnardb6f45a62013-12-04 21:54:36 +01001798 /*
1799 * if (b) R = 2R + P else R = 2R,
1800 * which is:
1801 * if (b) double_add( RP, R, RP, R )
1802 * else double_add( R, RP, R, RP )
1803 * but using safe conditional swaps to avoid leaks
1804 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001805 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1806 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
1807 MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) );
1808 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) );
1809 MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001810 }
1811
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001812 /*
1813 * Knowledge of the projective coordinates may leak the last few bits of the
1814 * scalar [1], and since our MPI implementation isn't constant-flow,
1815 * inversion (used for coordinate normalization) may leak the full value
1816 * of its input via side-channels [2].
1817 *
1818 * [1] https://eprint.iacr.org/2003/191
1819 * [2] https://eprint.iacr.org/2020/055
1820 *
1821 * Avoid the leak by randomizing coordinates before we normalize them.
1822 */
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001823#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001824 if( f_rng != NULL )
Manuel Pégourié-Gonnard22fe5232020-06-19 10:36:16 +02001825#endif
Manuel Pégourié-Gonnard54587fc2020-04-01 11:25:51 +02001826 MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
1827
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001828 MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001829
1830cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001831 mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001832
1833 return( ret );
1834}
1835
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001836#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnard7c94d8b2013-12-04 23:15:46 +01001837
Manuel Pégourié-Gonnardd9ea82e72013-12-03 12:02:28 +01001838/*
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001839 * Multiplication R = m * P
1840 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001841int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1842 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001843 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1844{
Janos Follathb0697532016-08-18 12:38:46 +01001845 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follathc44ab972016-11-18 16:38:23 +00001846#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1847 char is_grp_capable = 0;
1848#endif
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001849#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1850 ecp_drbg_context drbg_ctx;
1851
1852 ecp_drbg_init( &drbg_ctx );
1853#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001854
1855 /* Common sanity checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001856 if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 )
1857 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001858
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001859 if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 ||
1860 ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 )
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001861 return( ret );
1862
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001863#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1864 if( f_rng == NULL )
1865 {
1866 MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m ) );
1867 f_rng = &ecp_drbg_random;
1868 p_rng = &drbg_ctx;
1869 }
1870#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
1871
Janos Follathc44ab972016-11-18 16:38:23 +00001872#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001873 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01001874 {
Janos Follathc44ab972016-11-18 16:38:23 +00001875 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01001876 }
Janos Follathc44ab972016-11-18 16:38:23 +00001877#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001878
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001879#if defined(ECP_MONTGOMERY)
1880 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Janos Follathb0697532016-08-18 12:38:46 +01001881 ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng );
Janos Follath430d3372016-11-03 14:25:37 +00001882#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001883#if defined(ECP_SHORTWEIERSTRASS)
1884 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Janos Follathb0697532016-08-18 12:38:46 +01001885 ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng );
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001886#endif
Janos Follathb0697532016-08-18 12:38:46 +01001887
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001888#if defined(MBEDTLS_ECP_INTERNAL_ALT) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1889cleanup:
Janos Follath430d3372016-11-03 14:25:37 +00001890#endif
Janos Follathc44ab972016-11-18 16:38:23 +00001891#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00001892 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01001893 {
Janos Follathc44ab972016-11-18 16:38:23 +00001894 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01001895 }
Janos Follathc44ab972016-11-18 16:38:23 +00001896#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard75036a02020-05-22 12:12:36 +02001897
1898#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
1899 ecp_drbg_free( &drbg_ctx );
1900#endif
1901
Janos Follathb0697532016-08-18 12:38:46 +01001902 return( ret );
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001903}
1904
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001905#if defined(ECP_SHORTWEIERSTRASS)
Manuel Pégourié-Gonnarda0179b82013-12-04 11:49:20 +01001906/*
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01001907 * Check that an affine point is valid as a public key,
1908 * short weierstrass curves (SEC1 3.2.3.1)
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001909 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001910static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001911{
1912 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001913 mbedtls_mpi YY, RHS;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001914
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01001915 /* pt coordinates must be normalized for our checks */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001916 if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ||
1917 mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 ||
1918 mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
1919 mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
1920 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001921
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001922 mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001923
1924 /*
1925 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02001926 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001927 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001928 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
1929 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001930
1931 /* Special case for A = -3 */
1932 if( grp->A.p == NULL )
1933 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001934 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001935 }
1936 else
1937 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001938 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnard73cc01d2013-12-06 12:41:30 +01001939 }
1940
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001941 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
1942 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001943
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001944 if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 )
1945 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001946
1947cleanup:
1948
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001949 mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001950
1951 return( ret );
1952}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02001953#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01001954
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02001955/*
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02001956 * R = m * P with shortcuts for m == 1 and m == -1
1957 * NOT constant-time - ONLY for short Weierstrass!
1958 */
1959static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
1960 mbedtls_ecp_point *R,
1961 const mbedtls_mpi *m,
1962 const mbedtls_ecp_point *P )
1963{
1964 int ret;
1965
1966 if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
1967 {
1968 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
1969 }
1970 else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 )
1971 {
1972 MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) );
1973 if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 )
1974 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) );
1975 }
1976 else
1977 {
1978 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) );
1979 }
1980
1981cleanup:
1982 return( ret );
1983}
1984
1985/*
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02001986 * Linear combination
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02001987 * NOT constant-time
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02001988 */
1989int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
1990 const mbedtls_mpi *m, const mbedtls_ecp_point *P,
1991 const mbedtls_mpi *n, const mbedtls_ecp_point *Q )
1992{
1993 int ret;
1994 mbedtls_ecp_point mP;
Janos Follathc44ab972016-11-18 16:38:23 +00001995#if defined(MBEDTLS_ECP_INTERNAL_ALT)
1996 char is_grp_capable = 0;
1997#endif
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02001998
1999 if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS )
2000 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2001
2002 mbedtls_ecp_point_init( &mP );
2003
Manuel Pégourié-Gonnardde9f9532015-10-23 15:50:37 +02002004 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) );
2005 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) );
Manuel Pégourié-Gonnard1a7c5ef2015-08-13 10:19:09 +02002006
Janos Follathc44ab972016-11-18 16:38:23 +00002007#if defined(MBEDTLS_ECP_INTERNAL_ALT)
Janos Follathc44ab972016-11-18 16:38:23 +00002008 if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) )
Janos Follathb0697532016-08-18 12:38:46 +01002009 {
Janos Follathc44ab972016-11-18 16:38:23 +00002010 MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) );
Janos Follathb0697532016-08-18 12:38:46 +01002011 }
Janos Follath430d3372016-11-03 14:25:37 +00002012
Janos Follathc44ab972016-11-18 16:38:23 +00002013#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002014 MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) );
2015 MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) );
2016
2017cleanup:
Janos Follathb0697532016-08-18 12:38:46 +01002018
Janos Follathc44ab972016-11-18 16:38:23 +00002019#if defined(MBEDTLS_ECP_INTERNAL_ALT)
2020 if ( is_grp_capable )
Janos Follathb0697532016-08-18 12:38:46 +01002021 {
Janos Follathc44ab972016-11-18 16:38:23 +00002022 mbedtls_internal_ecp_free( grp );
Janos Follathb0697532016-08-18 12:38:46 +01002023 }
Janos Follathb0697532016-08-18 12:38:46 +01002024
Janos Follathc44ab972016-11-18 16:38:23 +00002025#endif /* MBEDTLS_ECP_INTERNAL_ALT */
Manuel Pégourié-Gonnard56cc88a2015-05-11 18:40:45 +02002026 mbedtls_ecp_point_free( &mP );
2027
2028 return( ret );
2029}
2030
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002031
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002032#if defined(ECP_MONTGOMERY)
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002033/*
2034 * Check validity of a public key for Montgomery curves with x-only schemes
2035 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002036static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002037{
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002038 /* [Curve25519 p. 5] Just check X is the correct number of bytes */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002039 if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 )
2040 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002041
2042 return( 0 );
2043}
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002044#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002045
2046/*
2047 * Check that a point is valid as a public key
2048 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002049int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002050{
2051 /* Must use affine coordinates */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002052 if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 )
2053 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002054
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002055#if defined(ECP_MONTGOMERY)
2056 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002057 return( ecp_check_pubkey_mx( grp, pt ) );
2058#endif
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002059#if defined(ECP_SHORTWEIERSTRASS)
2060 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002061 return( ecp_check_pubkey_sw( grp, pt ) );
2062#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002063 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002064}
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002065
2066/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002067 * Check that an mbedtls_mpi is valid as a private key
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002068 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002069int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002070{
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002071#if defined(ECP_MONTGOMERY)
2072 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002073 {
Manuel Pégourié-Gonnard07894332015-06-23 00:18:41 +02002074 /* see [Curve25519] page 5 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002075 if( mbedtls_mpi_get_bit( d, 0 ) != 0 ||
2076 mbedtls_mpi_get_bit( d, 1 ) != 0 ||
2077 mbedtls_mpi_get_bit( d, 2 ) != 0 ||
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002078 mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002079 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002080 else
2081 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002082 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002083#endif /* ECP_MONTGOMERY */
2084#if defined(ECP_SHORTWEIERSTRASS)
2085 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002086 {
2087 /* see SEC1 3.2 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002088 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
2089 mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
2090 return( MBEDTLS_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002091 else
2092 return( 0 );
Manuel Pégourié-Gonnard312d2e82013-12-04 11:08:01 +01002093 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002094#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002095
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002096 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02002097}
2098
2099/*
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002100 * Generate a private key
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002101 */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002102int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
2103 mbedtls_mpi *d,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002104 int (*f_rng)(void *, unsigned char *, size_t),
2105 void *p_rng )
2106{
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002107 int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker66d5d072014-06-17 16:39:18 +02002108 size_t n_size = ( grp->nbits + 7 ) / 8;
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002109
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002110#if defined(ECP_MONTGOMERY)
2111 if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002112 {
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002113 /* [M225] page 5 */
2114 size_t b;
2115
Janos Follath98e28a72016-05-31 14:03:54 +01002116 do {
2117 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
2118 } while( mbedtls_mpi_bitlen( d ) == 0);
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002119
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002120 /* Make sure the most significant bit is nbits */
Manuel Pégourié-Gonnardc0696c22015-06-18 16:47:17 +02002121 b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002122 if( b > grp->nbits )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002123 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002124 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002125 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002126
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002127 /* Make sure the last three bits are unset */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002128 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
2129 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
2130 MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002131 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002132#endif /* ECP_MONTGOMERY */
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002133
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002134#if defined(ECP_SHORTWEIERSTRASS)
2135 if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002136 {
2137 /* SEC1 3.2.1: Generate d such that 1 <= n < N */
Manuel Pégourié-Gonnardd9622732013-12-05 10:06:06 +01002138 int count = 0;
Janos Follathc3b376e2019-10-11 14:21:53 +01002139 unsigned cmp = 0;
Manuel Pégourié-Gonnard79f73b92014-01-03 12:35:05 +01002140
2141 /*
2142 * Match the procedure given in RFC 6979 (deterministic ECDSA):
2143 * - use the same byte ordering;
2144 * - keep the leftmost nbits bits of the generated octet string;
2145 * - try until result is in the desired range.
2146 * This also avoids any biais, which is especially important for ECDSA.
2147 */
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002148 do
2149 {
Hanno Becker7c8cb9c2017-10-17 15:19:38 +01002150 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002151 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002152
Manuel Pégourié-Gonnard6e8e34d2014-01-28 19:30:56 +01002153 /*
2154 * Each try has at worst a probability 1/2 of failing (the msb has
2155 * a probability 1/2 of being 0, and then the result will be < N),
2156 * so after 30 tries failure probability is a most 2**(-30).
2157 *
2158 * For most curves, 1 try is enough with overwhelming probability,
2159 * since N starts with a lot of 1s in binary, but some curves
2160 * such as secp224k1 are actually very close to the worst case.
2161 */
2162 if( ++count > 30 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002163 return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
Janos Follath5f3019b2019-09-16 14:27:39 +01002164
Janos Follathc3b376e2019-10-11 14:21:53 +01002165 ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
Janos Follath5f3019b2019-09-16 14:27:39 +01002166 if( ret != 0 )
2167 {
2168 goto cleanup;
2169 }
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002170 }
Janos Follathc3b376e2019-10-11 14:21:53 +01002171 while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
Manuel Pégourié-Gonnardfe0af402013-12-04 18:14:55 +01002172 }
Manuel Pégourié-Gonnard8408a942015-04-09 12:14:31 +02002173#endif /* ECP_SHORTWEIERSTRASS */
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002174
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002175cleanup:
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002176 return( ret );
2177}
Manuel Pégourié-Gonnardc9573992014-01-03 12:54:00 +01002178
Manuel Pégourié-Gonnardc80555d2017-04-20 15:37:46 +02002179/*
2180 * Generate a keypair with configurable base point
2181 */
2182int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
2183 const mbedtls_ecp_point *G,
2184 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2185 int (*f_rng)(void *, unsigned char *, size_t),
2186 void *p_rng )
2187{
2188 int ret;
2189
2190 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
2191 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
2192
2193cleanup:
2194 return( ret );
Manuel Pégourié-Gonnardd9a3f472015-08-11 14:31:03 +02002195}
2196
2197/*
2198 * Generate key pair, wrapper for conventional base point
2199 */
2200int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
2201 mbedtls_mpi *d, mbedtls_ecp_point *Q,
2202 int (*f_rng)(void *, unsigned char *, size_t),
2203 void *p_rng )
2204{
2205 return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01002206}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01002207
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002208/*
2209 * Generate a keypair, prettier wrapper
2210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002211int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002212 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
2213{
2214 int ret;
2215
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002216 if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 )
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002217 return( ret );
2218
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002219 return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard104ee1d2013-11-30 14:13:16 +01002220}
2221
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002222/*
2223 * Check a public-private key pair
2224 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002225int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002226{
2227 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002228 mbedtls_ecp_point Q;
2229 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002231 if( pub->grp.id == MBEDTLS_ECP_DP_NONE ||
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002232 pub->grp.id != prv->grp.id ||
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002233 mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) ||
2234 mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) ||
2235 mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002236 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002237 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002238 }
2239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002240 mbedtls_ecp_point_init( &Q );
2241 mbedtls_ecp_group_init( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002242
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002243 /* mbedtls_ecp_mul() needs a non-const group... */
2244 mbedtls_ecp_group_copy( &grp, &prv->grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002245
2246 /* Also checks d is valid */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002247 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002249 if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) ||
2250 mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) ||
2251 mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) )
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002252 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002253 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002254 goto cleanup;
2255 }
2256
2257cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002258 mbedtls_ecp_point_free( &Q );
2259 mbedtls_ecp_group_free( &grp );
Manuel Pégourié-Gonnard30668d62014-11-06 15:25:32 +01002260
2261 return( ret );
2262}
2263
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002264#if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002265
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01002266/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002267 * Checkup routine
2268 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002269int mbedtls_ecp_self_test( int verbose )
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002270{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002271 int ret;
2272 size_t i;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002273 mbedtls_ecp_group grp;
2274 mbedtls_ecp_point R, P;
2275 mbedtls_mpi m;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002276 unsigned long add_c_prev, dbl_c_prev, mul_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002277 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02002278 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002279 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002280 "000000000000000000000000000000000000000000000001", /* one */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002281 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01002282 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardff27b7c2013-11-21 09:28:03 +01002283 "400000000000000000000000000000000000000000000000", /* one and zeros */
2284 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */
2285 "555555555555555555555555555555555555555555555555", /* 101010... */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002286 };
2287
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002288 mbedtls_ecp_group_init( &grp );
2289 mbedtls_ecp_point_init( &R );
2290 mbedtls_ecp_point_init( &P );
2291 mbedtls_mpi_init( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002292
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002293 /* Use secp192r1 if available, or any available curve */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002294#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002295 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02002296#else
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +02002297 MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) );
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02002298#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002299
2300 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002301 mbedtls_printf( " ECP test #1 (constant op_count, base point G): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002302
2303 /* Do a dummy multiplication first to trigger precomputation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002304 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) );
2305 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002306
2307 add_count = 0;
2308 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002309 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002310 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2311 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002312
2313 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2314 {
2315 add_c_prev = add_count;
2316 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002317 mul_c_prev = mul_count;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002318 add_count = 0;
2319 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002320 mul_count = 0;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002321
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002322 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2323 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002324
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002325 if( add_count != add_c_prev ||
2326 dbl_count != dbl_c_prev ||
2327 mul_count != mul_c_prev )
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002328 {
2329 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002330 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002331
2332 ret = 1;
2333 goto cleanup;
2334 }
2335 }
2336
2337 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002338 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002339
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002340 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002341 mbedtls_printf( " ECP test #2 (constant op_count, other point): " );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002342 /* We computed P = 2G last time, use it */
2343
2344 add_count = 0;
2345 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002346 mul_count = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002347 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) );
2348 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002349
2350 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
2351 {
2352 add_c_prev = add_count;
2353 dbl_c_prev = dbl_count;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002354 mul_c_prev = mul_count;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002355 add_count = 0;
2356 dbl_count = 0;
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002357 mul_count = 0;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002359 MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) );
2360 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002361
Manuel Pégourié-Gonnard91814812013-11-21 20:23:55 +01002362 if( add_count != add_c_prev ||
2363 dbl_count != dbl_c_prev ||
2364 mul_count != mul_c_prev )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002365 {
2366 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002367 mbedtls_printf( "failed (%u)\n", (unsigned int) i );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002368
2369 ret = 1;
2370 goto cleanup;
2371 }
2372 }
2373
2374 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002375 mbedtls_printf( "passed\n" );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02002376
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002377cleanup:
2378
2379 if( ret < 0 && verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002380 mbedtls_printf( "Unexpected error, return code = %08X\n", ret );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002381
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002382 mbedtls_ecp_group_free( &grp );
2383 mbedtls_ecp_point_free( &R );
2384 mbedtls_ecp_point_free( &P );
2385 mbedtls_mpi_free( &m );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002386
2387 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002388 mbedtls_printf( "\n" );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01002389
2390 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002391}
2392
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002393#endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01002394
Janos Follathb0697532016-08-18 12:38:46 +01002395#endif /* !MBEDTLS_ECP_ALT */
2396
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02002397#endif /* MBEDTLS_ECP_C */