]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Elliptic curves over GF(p): generic functions | |
3 | * | |
4 | * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved | |
5 | * SPDX-License-Identifier: GPL-2.0 | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 | * | |
21 | * This file is part of mbed TLS (https://tls.mbed.org) | |
22 | */ | |
23 | ||
24 | /* | |
25 | * References: | |
26 | * | |
27 | * SEC1 http://www.secg.org/index.php?action=secg,docs_secg | |
28 | * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone | |
29 | * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf | |
30 | * RFC 4492 for the related TLS structures and constants | |
31 | * RFC 7748 for the Curve448 and Curve25519 curve definitions | |
32 | * | |
33 | * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf | |
34 | * | |
35 | * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis | |
36 | * for elliptic curve cryptosystems. In : Cryptographic Hardware and | |
37 | * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. | |
38 | * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25> | |
39 | * | |
40 | * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to | |
41 | * render ECC resistant against Side Channel Attacks. IACR Cryptology | |
42 | * ePrint Archive, 2004, vol. 2004, p. 342. | |
43 | * <http://eprint.iacr.org/2004/342.pdf> | |
44 | */ | |
45 | ||
46 | #if !defined(MBEDTLS_CONFIG_FILE) | |
47 | #include "mbedtls/config.h" | |
48 | #else | |
49 | #include MBEDTLS_CONFIG_FILE | |
50 | #endif | |
51 | ||
52 | #if defined(MBEDTLS_ECP_C) | |
53 | ||
54 | #include "mbedtls/ecp.h" | |
55 | #include "mbedtls/threading.h" | |
56 | #include "mbedtls/platform_util.h" | |
57 | ||
58 | #include <string.h> | |
59 | ||
60 | #if !defined(MBEDTLS_ECP_ALT) | |
61 | ||
62 | #if defined(MBEDTLS_PLATFORM_C) | |
63 | #include "mbedtls/platform.h" | |
64 | #else | |
65 | #include <stdlib.h> | |
66 | #include <stdio.h> | |
67 | #define mbedtls_printf printf | |
68 | #define mbedtls_calloc calloc | |
69 | #define mbedtls_free free | |
70 | #endif | |
71 | ||
72 | #include "mbedtls/ecp_internal.h" | |
73 | ||
74 | #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ | |
75 | !defined(inline) && !defined(__cplusplus) | |
76 | #define inline __inline | |
77 | #endif | |
78 | ||
79 | #if defined(MBEDTLS_SELF_TEST) | |
80 | /* | |
81 | * Counts of point addition and doubling, and field multiplications. | |
82 | * Used to test resistance of point multiplication to simple timing attacks. | |
83 | */ | |
84 | static unsigned long add_count, dbl_count, mul_count; | |
85 | #endif | |
86 | ||
87 | #if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) || \ | |
88 | defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ | |
89 | defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ | |
90 | defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ | |
91 | defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ | |
92 | defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ | |
93 | defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ | |
94 | defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ | |
95 | defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ | |
96 | defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ | |
97 | defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ | |
98 | defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) | |
99 | #define ECP_SHORTWEIERSTRASS | |
100 | #endif | |
101 | ||
102 | #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ | |
103 | defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) | |
104 | #define ECP_MONTGOMERY | |
105 | #endif | |
106 | ||
107 | /* | |
108 | * Curve types: internal for now, might be exposed later | |
109 | */ | |
110 | typedef enum | |
111 | { | |
112 | ECP_TYPE_NONE = 0, | |
113 | ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ | |
114 | ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ | |
115 | } ecp_curve_type; | |
116 | ||
117 | /* | |
118 | * List of supported curves: | |
119 | * - internal ID | |
120 | * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) | |
121 | * - size in bits | |
122 | * - readable name | |
123 | * | |
124 | * Curves are listed in order: largest curves first, and for a given size, | |
125 | * fastest curves first. This provides the default order for the SSL module. | |
126 | * | |
127 | * Reminder: update profiles in x509_crt.c when adding a new curves! | |
128 | */ | |
129 | static const mbedtls_ecp_curve_info ecp_supported_curves[] = | |
130 | { | |
131 | #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) | |
132 | { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, | |
133 | #endif | |
134 | #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) | |
135 | { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, | |
136 | #endif | |
137 | #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) | |
138 | { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, | |
139 | #endif | |
140 | #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) | |
141 | { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, | |
142 | #endif | |
143 | #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) | |
144 | { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, | |
145 | #endif | |
146 | #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) | |
147 | { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, | |
148 | #endif | |
149 | #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) | |
150 | { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, | |
151 | #endif | |
152 | #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) | |
153 | { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, | |
154 | #endif | |
155 | #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) | |
156 | { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, | |
157 | #endif | |
158 | #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) | |
159 | { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, | |
160 | #endif | |
161 | #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) | |
162 | { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, | |
163 | #endif | |
164 | #if defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) | |
165 | { MBEDTLS_ECP_DP_SECP128R1, 0xFE00, 128, "secp128r1" }, | |
166 | #endif | |
167 | { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, | |
168 | }; | |
169 | ||
170 | #define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ | |
171 | sizeof( ecp_supported_curves[0] ) | |
172 | ||
173 | static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; | |
174 | ||
175 | /* | |
176 | * List of supported curves and associated info | |
177 | */ | |
178 | const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) | |
179 | { | |
180 | return( ecp_supported_curves ); | |
181 | } | |
182 | ||
183 | /* | |
184 | * List of supported curves, group ID only | |
185 | */ | |
186 | const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) | |
187 | { | |
188 | static int init_done = 0; | |
189 | ||
190 | if( ! init_done ) | |
191 | { | |
192 | size_t i = 0; | |
193 | const mbedtls_ecp_curve_info *curve_info; | |
194 | ||
195 | for( curve_info = mbedtls_ecp_curve_list(); | |
196 | curve_info->grp_id != MBEDTLS_ECP_DP_NONE; | |
197 | curve_info++ ) | |
198 | { | |
199 | ecp_supported_grp_id[i++] = curve_info->grp_id; | |
200 | } | |
201 | ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; | |
202 | ||
203 | init_done = 1; | |
204 | } | |
205 | ||
206 | return( ecp_supported_grp_id ); | |
207 | } | |
208 | ||
209 | /* | |
210 | * Get the curve info for the internal identifier | |
211 | */ | |
212 | const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) | |
213 | { | |
214 | const mbedtls_ecp_curve_info *curve_info; | |
215 | ||
216 | for( curve_info = mbedtls_ecp_curve_list(); | |
217 | curve_info->grp_id != MBEDTLS_ECP_DP_NONE; | |
218 | curve_info++ ) | |
219 | { | |
220 | if( curve_info->grp_id == grp_id ) | |
221 | return( curve_info ); | |
222 | } | |
223 | ||
224 | return( NULL ); | |
225 | } | |
226 | ||
227 | /* | |
228 | * Get the curve info from the TLS identifier | |
229 | */ | |
230 | const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) | |
231 | { | |
232 | const mbedtls_ecp_curve_info *curve_info; | |
233 | ||
234 | for( curve_info = mbedtls_ecp_curve_list(); | |
235 | curve_info->grp_id != MBEDTLS_ECP_DP_NONE; | |
236 | curve_info++ ) | |
237 | { | |
238 | if( curve_info->tls_id == tls_id ) | |
239 | return( curve_info ); | |
240 | } | |
241 | ||
242 | return( NULL ); | |
243 | } | |
244 | ||
245 | /* | |
246 | * Get the curve info from the name | |
247 | */ | |
248 | const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) | |
249 | { | |
250 | const mbedtls_ecp_curve_info *curve_info; | |
251 | ||
252 | for( curve_info = mbedtls_ecp_curve_list(); | |
253 | curve_info->grp_id != MBEDTLS_ECP_DP_NONE; | |
254 | curve_info++ ) | |
255 | { | |
256 | if( strcmp( curve_info->name, name ) == 0 ) | |
257 | return( curve_info ); | |
258 | } | |
259 | ||
260 | return( NULL ); | |
261 | } | |
262 | ||
263 | /* | |
264 | * Get the type of a curve | |
265 | */ | |
266 | static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) | |
267 | { | |
268 | if( grp->G.X.p == NULL ) | |
269 | return( ECP_TYPE_NONE ); | |
270 | ||
271 | if( grp->G.Y.p == NULL ) | |
272 | return( ECP_TYPE_MONTGOMERY ); | |
273 | else | |
274 | return( ECP_TYPE_SHORT_WEIERSTRASS ); | |
275 | } | |
276 | ||
277 | /* | |
278 | * Initialize (the components of) a point | |
279 | */ | |
280 | void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) | |
281 | { | |
282 | if( pt == NULL ) | |
283 | return; | |
284 | ||
285 | mbedtls_mpi_init( &pt->X ); | |
286 | mbedtls_mpi_init( &pt->Y ); | |
287 | mbedtls_mpi_init( &pt->Z ); | |
288 | } | |
289 | ||
290 | /* | |
291 | * Initialize (the components of) a group | |
292 | */ | |
293 | void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) | |
294 | { | |
295 | if( grp == NULL ) | |
296 | return; | |
297 | ||
298 | memset( grp, 0, sizeof( mbedtls_ecp_group ) ); | |
299 | } | |
300 | ||
301 | /* | |
302 | * Initialize (the components of) a key pair | |
303 | */ | |
304 | void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) | |
305 | { | |
306 | if( key == NULL ) | |
307 | return; | |
308 | ||
309 | mbedtls_ecp_group_init( &key->grp ); | |
310 | mbedtls_mpi_init( &key->d ); | |
311 | mbedtls_ecp_point_init( &key->Q ); | |
312 | } | |
313 | ||
314 | /* | |
315 | * Unallocate (the components of) a point | |
316 | */ | |
317 | void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) | |
318 | { | |
319 | if( pt == NULL ) | |
320 | return; | |
321 | ||
322 | mbedtls_mpi_free( &( pt->X ) ); | |
323 | mbedtls_mpi_free( &( pt->Y ) ); | |
324 | mbedtls_mpi_free( &( pt->Z ) ); | |
325 | } | |
326 | ||
327 | /* | |
328 | * Unallocate (the components of) a group | |
329 | */ | |
330 | void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) | |
331 | { | |
332 | size_t i; | |
333 | ||
334 | if( grp == NULL ) | |
335 | return; | |
336 | ||
337 | if( grp->h != 1 ) | |
338 | { | |
339 | mbedtls_mpi_free( &grp->P ); | |
340 | mbedtls_mpi_free( &grp->A ); | |
341 | mbedtls_mpi_free( &grp->B ); | |
342 | mbedtls_ecp_point_free( &grp->G ); | |
343 | mbedtls_mpi_free( &grp->N ); | |
344 | } | |
345 | ||
346 | if( grp->T != NULL ) | |
347 | { | |
348 | for( i = 0; i < grp->T_size; i++ ) | |
349 | mbedtls_ecp_point_free( &grp->T[i] ); | |
350 | mbedtls_free( grp->T ); | |
351 | } | |
352 | ||
353 | mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); | |
354 | } | |
355 | ||
356 | /* | |
357 | * Unallocate (the components of) a key pair | |
358 | */ | |
359 | void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) | |
360 | { | |
361 | if( key == NULL ) | |
362 | return; | |
363 | ||
364 | mbedtls_ecp_group_free( &key->grp ); | |
365 | mbedtls_mpi_free( &key->d ); | |
366 | mbedtls_ecp_point_free( &key->Q ); | |
367 | } | |
368 | ||
369 | /* | |
370 | * Copy the contents of a point | |
371 | */ | |
372 | int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) | |
373 | { | |
374 | int ret; | |
375 | ||
376 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); | |
377 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); | |
378 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); | |
379 | ||
380 | cleanup: | |
381 | return( ret ); | |
382 | } | |
383 | ||
384 | /* | |
385 | * Copy the contents of a group object | |
386 | */ | |
387 | int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) | |
388 | { | |
389 | return mbedtls_ecp_group_load( dst, src->id ); | |
390 | } | |
391 | ||
392 | /* | |
393 | * Set point to zero | |
394 | */ | |
395 | int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) | |
396 | { | |
397 | int ret; | |
398 | ||
399 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); | |
400 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); | |
401 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); | |
402 | ||
403 | cleanup: | |
404 | return( ret ); | |
405 | } | |
406 | ||
407 | /* | |
408 | * Tell if a point is zero | |
409 | */ | |
410 | int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) | |
411 | { | |
412 | return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); | |
413 | } | |
414 | ||
415 | /* | |
416 | * Compare two points lazyly | |
417 | */ | |
418 | int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, | |
419 | const mbedtls_ecp_point *Q ) | |
420 | { | |
421 | if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && | |
422 | mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && | |
423 | mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) | |
424 | { | |
425 | return( 0 ); | |
426 | } | |
427 | ||
428 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
429 | } | |
430 | ||
431 | /* | |
432 | * Import a non-zero point from ASCII strings | |
433 | */ | |
434 | int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, | |
435 | const char *x, const char *y ) | |
436 | { | |
437 | int ret; | |
438 | ||
439 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); | |
440 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); | |
441 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); | |
442 | ||
443 | cleanup: | |
444 | return( ret ); | |
445 | } | |
446 | ||
447 | /* | |
448 | * Export a point into unsigned binary data (SEC1 2.3.3) | |
449 | */ | |
450 | int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, | |
451 | int format, size_t *olen, | |
452 | unsigned char *buf, size_t buflen ) | |
453 | { | |
454 | int ret = 0; | |
455 | size_t plen; | |
456 | ||
457 | if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && | |
458 | format != MBEDTLS_ECP_PF_COMPRESSED ) | |
459 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
460 | ||
461 | /* | |
462 | * Common case: P == 0 | |
463 | */ | |
464 | if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) | |
465 | { | |
466 | if( buflen < 1 ) | |
467 | return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); | |
468 | ||
469 | buf[0] = 0x00; | |
470 | *olen = 1; | |
471 | ||
472 | return( 0 ); | |
473 | } | |
474 | ||
475 | plen = mbedtls_mpi_size( &grp->P ); | |
476 | ||
477 | if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) | |
478 | { | |
479 | *olen = 2 * plen + 1; | |
480 | ||
481 | if( buflen < *olen ) | |
482 | return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); | |
483 | ||
484 | buf[0] = 0x04; | |
485 | MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); | |
486 | MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); | |
487 | } | |
488 | else if( format == MBEDTLS_ECP_PF_COMPRESSED ) | |
489 | { | |
490 | *olen = plen + 1; | |
491 | ||
492 | if( buflen < *olen ) | |
493 | return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); | |
494 | ||
495 | buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); | |
496 | MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); | |
497 | } | |
498 | ||
499 | cleanup: | |
500 | return( ret ); | |
501 | } | |
502 | ||
503 | /* | |
504 | * Import a point from unsigned binary data (SEC1 2.3.4) | |
505 | */ | |
506 | int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, | |
507 | const unsigned char *buf, size_t ilen ) | |
508 | { | |
509 | int ret; | |
510 | size_t plen; | |
511 | ||
512 | if( ilen < 1 ) | |
513 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
514 | ||
515 | if( buf[0] == 0x00 ) | |
516 | { | |
517 | if( ilen == 1 ) | |
518 | return( mbedtls_ecp_set_zero( pt ) ); | |
519 | else | |
520 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
521 | } | |
522 | ||
523 | plen = mbedtls_mpi_size( &grp->P ); | |
524 | ||
525 | if( buf[0] != 0x04 ) | |
526 | return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); | |
527 | ||
528 | if( ilen != 2 * plen + 1 ) | |
529 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
530 | ||
531 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); | |
532 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); | |
533 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); | |
534 | ||
535 | cleanup: | |
536 | return( ret ); | |
537 | } | |
538 | ||
539 | /* | |
540 | * Import a point from a TLS ECPoint record (RFC 4492) | |
541 | * struct { | |
542 | * opaque point <1..2^8-1>; | |
543 | * } ECPoint; | |
544 | */ | |
545 | int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, | |
546 | const unsigned char **buf, size_t buf_len ) | |
547 | { | |
548 | unsigned char data_len; | |
549 | const unsigned char *buf_start; | |
550 | ||
551 | /* | |
552 | * We must have at least two bytes (1 for length, at least one for data) | |
553 | */ | |
554 | if( buf_len < 2 ) | |
555 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
556 | ||
557 | data_len = *(*buf)++; | |
558 | if( data_len < 1 || data_len > buf_len - 1 ) | |
559 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
560 | ||
561 | /* | |
562 | * Save buffer start for read_binary and update buf | |
563 | */ | |
564 | buf_start = *buf; | |
565 | *buf += data_len; | |
566 | ||
567 | return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); | |
568 | } | |
569 | ||
570 | /* | |
571 | * Export a point as a TLS ECPoint record (RFC 4492) | |
572 | * struct { | |
573 | * opaque point <1..2^8-1>; | |
574 | * } ECPoint; | |
575 | */ | |
576 | int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, | |
577 | int format, size_t *olen, | |
578 | unsigned char *buf, size_t blen ) | |
579 | { | |
580 | int ret; | |
581 | ||
582 | /* | |
583 | * buffer length must be at least one, for our length byte | |
584 | */ | |
585 | if( blen < 1 ) | |
586 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
587 | ||
588 | if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, | |
589 | olen, buf + 1, blen - 1) ) != 0 ) | |
590 | return( ret ); | |
591 | ||
592 | /* | |
593 | * write length to the first byte and update total length | |
594 | */ | |
595 | buf[0] = (unsigned char) *olen; | |
596 | ++*olen; | |
597 | ||
598 | return( 0 ); | |
599 | } | |
600 | ||
601 | /* | |
602 | * Set a group from an ECParameters record (RFC 4492) | |
603 | */ | |
604 | int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) | |
605 | { | |
606 | uint16_t tls_id; | |
607 | const mbedtls_ecp_curve_info *curve_info; | |
608 | ||
609 | /* | |
610 | * We expect at least three bytes (see below) | |
611 | */ | |
612 | if( len < 3 ) | |
613 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
614 | ||
615 | /* | |
616 | * First byte is curve_type; only named_curve is handled | |
617 | */ | |
618 | if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) | |
619 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
620 | ||
621 | /* | |
622 | * Next two bytes are the namedcurve value | |
623 | */ | |
624 | tls_id = *(*buf)++; | |
625 | tls_id <<= 8; | |
626 | tls_id |= *(*buf)++; | |
627 | ||
628 | if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) | |
629 | return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); | |
630 | ||
631 | return mbedtls_ecp_group_load( grp, curve_info->grp_id ); | |
632 | } | |
633 | ||
634 | /* | |
635 | * Write the ECParameters record corresponding to a group (RFC 4492) | |
636 | */ | |
637 | int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, | |
638 | unsigned char *buf, size_t blen ) | |
639 | { | |
640 | const mbedtls_ecp_curve_info *curve_info; | |
641 | ||
642 | if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) | |
643 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
644 | ||
645 | /* | |
646 | * We are going to write 3 bytes (see below) | |
647 | */ | |
648 | *olen = 3; | |
649 | if( blen < *olen ) | |
650 | return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); | |
651 | ||
652 | /* | |
653 | * First byte is curve_type, always named_curve | |
654 | */ | |
655 | *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; | |
656 | ||
657 | /* | |
658 | * Next two bytes are the namedcurve value | |
659 | */ | |
660 | buf[0] = curve_info->tls_id >> 8; | |
661 | buf[1] = curve_info->tls_id & 0xFF; | |
662 | ||
663 | return( 0 ); | |
664 | } | |
665 | ||
666 | /* | |
667 | * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. | |
668 | * See the documentation of struct mbedtls_ecp_group. | |
669 | * | |
670 | * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. | |
671 | */ | |
672 | static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) | |
673 | { | |
674 | int ret; | |
675 | ||
676 | if( grp->modp == NULL ) | |
677 | return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); | |
678 | ||
679 | /* N->s < 0 is a much faster test, which fails only if N is 0 */ | |
680 | if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || | |
681 | mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) | |
682 | { | |
683 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
684 | } | |
685 | ||
686 | MBEDTLS_MPI_CHK( grp->modp( N ) ); | |
687 | ||
688 | /* N->s < 0 is a much faster test, which fails only if N is 0 */ | |
689 | while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) | |
690 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); | |
691 | ||
692 | while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) | |
693 | /* we known P, N and the result are positive */ | |
694 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); | |
695 | ||
696 | cleanup: | |
697 | return( ret ); | |
698 | } | |
699 | ||
700 | /* | |
701 | * Fast mod-p functions expect their argument to be in the 0..p^2 range. | |
702 | * | |
703 | * In order to guarantee that, we need to ensure that operands of | |
704 | * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will | |
705 | * bring the result back to this range. | |
706 | * | |
707 | * The following macros are shortcuts for doing that. | |
708 | */ | |
709 | ||
710 | /* | |
711 | * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi | |
712 | */ | |
713 | #if defined(MBEDTLS_SELF_TEST) | |
714 | #define INC_MUL_COUNT mul_count++; | |
715 | #else | |
716 | #define INC_MUL_COUNT | |
717 | #endif | |
718 | ||
719 | #define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ | |
720 | while( 0 ) | |
721 | ||
722 | /* | |
723 | * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi | |
724 | * N->s < 0 is a very fast test, which fails only if N is 0 | |
725 | */ | |
726 | #define MOD_SUB( N ) \ | |
727 | while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ | |
728 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) | |
729 | ||
730 | /* | |
731 | * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. | |
732 | * We known P, N and the result are positive, so sub_abs is correct, and | |
733 | * a bit faster. | |
734 | */ | |
735 | #define MOD_ADD( N ) \ | |
736 | while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ | |
737 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) | |
738 | ||
739 | #if defined(ECP_SHORTWEIERSTRASS) | |
740 | /* | |
741 | * For curves in short Weierstrass form, we do all the internal operations in | |
742 | * Jacobian coordinates. | |
743 | * | |
744 | * For multiplication, we'll use a comb method with coutermeasueres against | |
745 | * SPA, hence timing attacks. | |
746 | */ | |
747 | ||
748 | /* | |
749 | * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) | |
750 | * Cost: 1N := 1I + 3M + 1S | |
751 | */ | |
752 | static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) | |
753 | { | |
754 | int ret; | |
755 | mbedtls_mpi Zi, ZZi; | |
756 | ||
757 | if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) | |
758 | return( 0 ); | |
759 | ||
760 | #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) | |
761 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
762 | { | |
763 | return mbedtls_internal_ecp_normalize_jac( grp, pt ); | |
764 | } | |
765 | #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ | |
766 | mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); | |
767 | ||
768 | /* | |
769 | * X = X / Z^2 mod p | |
770 | */ | |
771 | MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); | |
772 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); | |
773 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); | |
774 | ||
775 | /* | |
776 | * Y = Y / Z^3 mod p | |
777 | */ | |
778 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); | |
779 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); | |
780 | ||
781 | /* | |
782 | * Z = 1 | |
783 | */ | |
784 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); | |
785 | ||
786 | cleanup: | |
787 | ||
788 | mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); | |
789 | ||
790 | return( ret ); | |
791 | } | |
792 | ||
793 | /* | |
794 | * Normalize jacobian coordinates of an array of (pointers to) points, | |
795 | * using Montgomery's trick to perform only one inversion mod P. | |
796 | * (See for example Cohen's "A Course in Computational Algebraic Number | |
797 | * Theory", Algorithm 10.3.4.) | |
798 | * | |
799 | * Warning: fails (returning an error) if one of the points is zero! | |
800 | * This should never happen, see choice of w in ecp_mul_comb(). | |
801 | * | |
802 | * Cost: 1N(t) := 1I + (6t - 3)M + 1S | |
803 | */ | |
804 | static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, | |
805 | mbedtls_ecp_point *T[], size_t t_len ) | |
806 | { | |
807 | int ret; | |
808 | size_t i; | |
809 | mbedtls_mpi *c, u, Zi, ZZi; | |
810 | ||
811 | if( t_len < 2 ) | |
812 | return( ecp_normalize_jac( grp, *T ) ); | |
813 | ||
814 | #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) | |
815 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
816 | { | |
817 | return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); | |
818 | } | |
819 | #endif | |
820 | ||
821 | if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) | |
822 | return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); | |
823 | ||
824 | mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); | |
825 | ||
826 | /* | |
827 | * c[i] = Z_0 * ... * Z_i | |
828 | */ | |
829 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); | |
830 | for( i = 1; i < t_len; i++ ) | |
831 | { | |
832 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); | |
833 | MOD_MUL( c[i] ); | |
834 | } | |
835 | ||
836 | /* | |
837 | * u = 1 / (Z_0 * ... * Z_n) mod P | |
838 | */ | |
839 | MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); | |
840 | ||
841 | for( i = t_len - 1; ; i-- ) | |
842 | { | |
843 | /* | |
844 | * Zi = 1 / Z_i mod p | |
845 | * u = 1 / (Z_0 * ... * Z_i) mod P | |
846 | */ | |
847 | if( i == 0 ) { | |
848 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); | |
849 | } | |
850 | else | |
851 | { | |
852 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); | |
853 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); | |
854 | } | |
855 | ||
856 | /* | |
857 | * proceed as in normalize() | |
858 | */ | |
859 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); | |
860 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); | |
861 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); | |
862 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); | |
863 | ||
864 | /* | |
865 | * Post-precessing: reclaim some memory by shrinking coordinates | |
866 | * - not storing Z (always 1) | |
867 | * - shrinking other coordinates, but still keeping the same number of | |
868 | * limbs as P, as otherwise it will too likely be regrown too fast. | |
869 | */ | |
870 | MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); | |
871 | MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); | |
872 | mbedtls_mpi_free( &T[i]->Z ); | |
873 | ||
874 | if( i == 0 ) | |
875 | break; | |
876 | } | |
877 | ||
878 | cleanup: | |
879 | ||
880 | mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); | |
881 | for( i = 0; i < t_len; i++ ) | |
882 | mbedtls_mpi_free( &c[i] ); | |
883 | mbedtls_free( c ); | |
884 | ||
885 | return( ret ); | |
886 | } | |
887 | ||
888 | /* | |
889 | * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. | |
890 | * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid | |
891 | */ | |
892 | static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, | |
893 | mbedtls_ecp_point *Q, | |
894 | unsigned char inv ) | |
895 | { | |
896 | int ret; | |
897 | unsigned char nonzero; | |
898 | mbedtls_mpi mQY; | |
899 | ||
900 | mbedtls_mpi_init( &mQY ); | |
901 | ||
902 | /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ | |
903 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); | |
904 | nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; | |
905 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); | |
906 | ||
907 | cleanup: | |
908 | mbedtls_mpi_free( &mQY ); | |
909 | ||
910 | return( ret ); | |
911 | } | |
912 | ||
913 | /* | |
914 | * Point doubling R = 2 P, Jacobian coordinates | |
915 | * | |
916 | * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . | |
917 | * | |
918 | * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR | |
919 | * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. | |
920 | * | |
921 | * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. | |
922 | * | |
923 | * Cost: 1D := 3M + 4S (A == 0) | |
924 | * 4M + 4S (A == -3) | |
925 | * 3M + 6S + 1a otherwise | |
926 | */ | |
927 | static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
928 | const mbedtls_ecp_point *P ) | |
929 | { | |
930 | int ret; | |
931 | mbedtls_mpi M, S, T, U; | |
932 | ||
933 | #if defined(MBEDTLS_SELF_TEST) | |
934 | dbl_count++; | |
935 | #endif | |
936 | ||
937 | #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) | |
938 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
939 | { | |
940 | return mbedtls_internal_ecp_double_jac( grp, R, P ); | |
941 | } | |
942 | #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ | |
943 | ||
944 | mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); | |
945 | ||
946 | /* Special case for A = -3 */ | |
947 | if( grp->A.p == NULL ) | |
948 | { | |
949 | /* M = 3(X + Z^2)(X - Z^2) */ | |
950 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); | |
951 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); | |
952 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); | |
953 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); | |
954 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); | |
955 | } | |
956 | else | |
957 | { | |
958 | /* M = 3.X^2 */ | |
959 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); | |
960 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); | |
961 | ||
962 | /* Optimize away for "koblitz" curves with A = 0 */ | |
963 | if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) | |
964 | { | |
965 | /* M += A.Z^4 */ | |
966 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); | |
967 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); | |
968 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); | |
969 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); | |
970 | } | |
971 | } | |
972 | ||
973 | /* S = 4.X.Y^2 */ | |
974 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); | |
975 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); | |
976 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); | |
977 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); | |
978 | ||
979 | /* U = 8.Y^4 */ | |
980 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); | |
981 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); | |
982 | ||
983 | /* T = M^2 - 2.S */ | |
984 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); | |
985 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); | |
986 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); | |
987 | ||
988 | /* S = M(S - T) - U */ | |
989 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); | |
990 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); | |
991 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); | |
992 | ||
993 | /* U = 2.Y.Z */ | |
994 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); | |
995 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); | |
996 | ||
997 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); | |
998 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); | |
999 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); | |
1000 | ||
1001 | cleanup: | |
1002 | mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); | |
1003 | ||
1004 | return( ret ); | |
1005 | } | |
1006 | ||
1007 | /* | |
1008 | * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) | |
1009 | * | |
1010 | * The coordinates of Q must be normalized (= affine), | |
1011 | * but those of P don't need to. R is not normalized. | |
1012 | * | |
1013 | * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. | |
1014 | * None of these cases can happen as intermediate step in ecp_mul_comb(): | |
1015 | * - at each step, P, Q and R are multiples of the base point, the factor | |
1016 | * being less than its order, so none of them is zero; | |
1017 | * - Q is an odd multiple of the base point, P an even multiple, | |
1018 | * due to the choice of precomputed points in the modified comb method. | |
1019 | * So branches for these cases do not leak secret information. | |
1020 | * | |
1021 | * We accept Q->Z being unset (saving memory in tables) as meaning 1. | |
1022 | * | |
1023 | * Cost: 1A := 8M + 3S | |
1024 | */ | |
1025 | static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1026 | const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) | |
1027 | { | |
1028 | int ret; | |
1029 | mbedtls_mpi T1, T2, T3, T4, X, Y, Z; | |
1030 | ||
1031 | #if defined(MBEDTLS_SELF_TEST) | |
1032 | add_count++; | |
1033 | #endif | |
1034 | ||
1035 | #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) | |
1036 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
1037 | { | |
1038 | return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); | |
1039 | } | |
1040 | #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ | |
1041 | ||
1042 | /* | |
1043 | * Trivial cases: P == 0 or Q == 0 (case 1) | |
1044 | */ | |
1045 | if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) | |
1046 | return( mbedtls_ecp_copy( R, Q ) ); | |
1047 | ||
1048 | if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) | |
1049 | return( mbedtls_ecp_copy( R, P ) ); | |
1050 | ||
1051 | /* | |
1052 | * Make sure Q coordinates are normalized | |
1053 | */ | |
1054 | if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) | |
1055 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
1056 | ||
1057 | mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); | |
1058 | mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); | |
1059 | ||
1060 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); | |
1061 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); | |
1062 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); | |
1063 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); | |
1064 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); | |
1065 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); | |
1066 | ||
1067 | /* Special cases (2) and (3) */ | |
1068 | if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) | |
1069 | { | |
1070 | if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) | |
1071 | { | |
1072 | ret = ecp_double_jac( grp, R, P ); | |
1073 | goto cleanup; | |
1074 | } | |
1075 | else | |
1076 | { | |
1077 | ret = mbedtls_ecp_set_zero( R ); | |
1078 | goto cleanup; | |
1079 | } | |
1080 | } | |
1081 | ||
1082 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); | |
1083 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); | |
1084 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); | |
1085 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); | |
1086 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); | |
1087 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); | |
1088 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); | |
1089 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); | |
1090 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); | |
1091 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); | |
1092 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); | |
1093 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); | |
1094 | ||
1095 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); | |
1096 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); | |
1097 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); | |
1098 | ||
1099 | cleanup: | |
1100 | ||
1101 | mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); | |
1102 | mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); | |
1103 | ||
1104 | return( ret ); | |
1105 | } | |
1106 | ||
1107 | /* | |
1108 | * Randomize jacobian coordinates: | |
1109 | * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l | |
1110 | * This is sort of the reverse operation of ecp_normalize_jac(). | |
1111 | * | |
1112 | * This countermeasure was first suggested in [2]. | |
1113 | */ | |
1114 | static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, | |
1115 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
1116 | { | |
1117 | int ret; | |
1118 | mbedtls_mpi l, ll; | |
1119 | size_t p_size; | |
1120 | int count = 0; | |
1121 | ||
1122 | #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) | |
1123 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
1124 | { | |
1125 | return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); | |
1126 | } | |
1127 | #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ | |
1128 | ||
1129 | p_size = ( grp->pbits + 7 ) / 8; | |
1130 | mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); | |
1131 | ||
1132 | /* Generate l such that 1 < l < p */ | |
1133 | do | |
1134 | { | |
1135 | MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); | |
1136 | ||
1137 | while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) | |
1138 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); | |
1139 | ||
1140 | if( count++ > 10 ) | |
1141 | return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); | |
1142 | } | |
1143 | while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); | |
1144 | ||
1145 | /* Z = l * Z */ | |
1146 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); | |
1147 | ||
1148 | /* X = l^2 * X */ | |
1149 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); | |
1150 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); | |
1151 | ||
1152 | /* Y = l^3 * Y */ | |
1153 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); | |
1154 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); | |
1155 | ||
1156 | cleanup: | |
1157 | mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); | |
1158 | ||
1159 | return( ret ); | |
1160 | } | |
1161 | ||
1162 | /* | |
1163 | * Check and define parameters used by the comb method (see below for details) | |
1164 | */ | |
1165 | #if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 | |
1166 | #error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" | |
1167 | #endif | |
1168 | ||
1169 | /* d = ceil( n / w ) */ | |
1170 | #define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 | |
1171 | ||
1172 | /* number of precomputed points */ | |
1173 | #define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) | |
1174 | ||
1175 | /* | |
1176 | * Compute the representation of m that will be used with our comb method. | |
1177 | * | |
1178 | * The basic comb method is described in GECC 3.44 for example. We use a | |
1179 | * modified version that provides resistance to SPA by avoiding zero | |
1180 | * digits in the representation as in [3]. We modify the method further by | |
1181 | * requiring that all K_i be odd, which has the small cost that our | |
1182 | * representation uses one more K_i, due to carries. | |
1183 | * | |
1184 | * Also, for the sake of compactness, only the seven low-order bits of x[i] | |
1185 | * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in | |
1186 | * the paper): it is set if and only if if s_i == -1; | |
1187 | * | |
1188 | * Calling conventions: | |
1189 | * - x is an array of size d + 1 | |
1190 | * - w is the size, ie number of teeth, of the comb, and must be between | |
1191 | * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) | |
1192 | * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d | |
1193 | * (the result will be incorrect if these assumptions are not satisfied) | |
1194 | */ | |
1195 | static void ecp_comb_fixed( unsigned char x[], size_t d, | |
1196 | unsigned char w, const mbedtls_mpi *m ) | |
1197 | { | |
1198 | size_t i, j; | |
1199 | unsigned char c, cc, adjust; | |
1200 | ||
1201 | memset( x, 0, d+1 ); | |
1202 | ||
1203 | /* First get the classical comb values (except for x_d = 0) */ | |
1204 | for( i = 0; i < d; i++ ) | |
1205 | for( j = 0; j < w; j++ ) | |
1206 | x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; | |
1207 | ||
1208 | /* Now make sure x_1 .. x_d are odd */ | |
1209 | c = 0; | |
1210 | for( i = 1; i <= d; i++ ) | |
1211 | { | |
1212 | /* Add carry and update it */ | |
1213 | cc = x[i] & c; | |
1214 | x[i] = x[i] ^ c; | |
1215 | c = cc; | |
1216 | ||
1217 | /* Adjust if needed, avoiding branches */ | |
1218 | adjust = 1 - ( x[i] & 0x01 ); | |
1219 | c |= x[i] & ( x[i-1] * adjust ); | |
1220 | x[i] = x[i] ^ ( x[i-1] * adjust ); | |
1221 | x[i-1] |= adjust << 7; | |
1222 | } | |
1223 | } | |
1224 | ||
1225 | /* | |
1226 | * Precompute points for the comb method | |
1227 | * | |
1228 | * If i = i_{w-1} ... i_1 is the binary representation of i, then | |
1229 | * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P | |
1230 | * | |
1231 | * T must be able to hold 2^{w - 1} elements | |
1232 | * | |
1233 | * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) | |
1234 | */ | |
1235 | static int ecp_precompute_comb( const mbedtls_ecp_group *grp, | |
1236 | mbedtls_ecp_point T[], const mbedtls_ecp_point *P, | |
1237 | unsigned char w, size_t d ) | |
1238 | { | |
1239 | int ret; | |
1240 | unsigned char i, k; | |
1241 | size_t j; | |
1242 | mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; | |
1243 | ||
1244 | /* | |
1245 | * Set T[0] = P and | |
1246 | * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) | |
1247 | */ | |
1248 | MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); | |
1249 | ||
1250 | k = 0; | |
1251 | for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) | |
1252 | { | |
1253 | cur = T + i; | |
1254 | MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); | |
1255 | for( j = 0; j < d; j++ ) | |
1256 | MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); | |
1257 | ||
1258 | TT[k++] = cur; | |
1259 | } | |
1260 | ||
1261 | MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); | |
1262 | ||
1263 | /* | |
1264 | * Compute the remaining ones using the minimal number of additions | |
1265 | * Be careful to update T[2^l] only after using it! | |
1266 | */ | |
1267 | k = 0; | |
1268 | for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) | |
1269 | { | |
1270 | j = i; | |
1271 | while( j-- ) | |
1272 | { | |
1273 | MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); | |
1274 | TT[k++] = &T[i + j]; | |
1275 | } | |
1276 | } | |
1277 | ||
1278 | MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); | |
1279 | ||
1280 | cleanup: | |
1281 | ||
1282 | return( ret ); | |
1283 | } | |
1284 | ||
1285 | /* | |
1286 | * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] | |
1287 | */ | |
1288 | static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1289 | const mbedtls_ecp_point T[], unsigned char t_len, | |
1290 | unsigned char i ) | |
1291 | { | |
1292 | int ret; | |
1293 | unsigned char ii, j; | |
1294 | ||
1295 | /* Ignore the "sign" bit and scale down */ | |
1296 | ii = ( i & 0x7Fu ) >> 1; | |
1297 | ||
1298 | /* Read the whole table to thwart cache-based timing attacks */ | |
1299 | for( j = 0; j < t_len; j++ ) | |
1300 | { | |
1301 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); | |
1302 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); | |
1303 | } | |
1304 | ||
1305 | /* Safely invert result if i is "negative" */ | |
1306 | MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); | |
1307 | ||
1308 | cleanup: | |
1309 | return( ret ); | |
1310 | } | |
1311 | ||
1312 | /* | |
1313 | * Core multiplication algorithm for the (modified) comb method. | |
1314 | * This part is actually common with the basic comb method (GECC 3.44) | |
1315 | * | |
1316 | * Cost: d A + d D + 1 R | |
1317 | */ | |
1318 | static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1319 | const mbedtls_ecp_point T[], unsigned char t_len, | |
1320 | const unsigned char x[], size_t d, | |
1321 | int (*f_rng)(void *, unsigned char *, size_t), | |
1322 | void *p_rng ) | |
1323 | { | |
1324 | int ret; | |
1325 | mbedtls_ecp_point Txi; | |
1326 | size_t i; | |
1327 | ||
1328 | mbedtls_ecp_point_init( &Txi ); | |
1329 | ||
1330 | /* Start with a non-zero point and randomize its coordinates */ | |
1331 | i = d; | |
1332 | MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); | |
1333 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); | |
1334 | if( f_rng != 0 ) | |
1335 | MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); | |
1336 | ||
1337 | while( i-- != 0 ) | |
1338 | { | |
1339 | MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); | |
1340 | MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); | |
1341 | MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); | |
1342 | } | |
1343 | ||
1344 | cleanup: | |
1345 | ||
1346 | mbedtls_ecp_point_free( &Txi ); | |
1347 | ||
1348 | return( ret ); | |
1349 | } | |
1350 | ||
1351 | /* | |
1352 | * Multiplication using the comb method, | |
1353 | * for curves in short Weierstrass form | |
1354 | */ | |
1355 | static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1356 | const mbedtls_mpi *m, const mbedtls_ecp_point *P, | |
1357 | int (*f_rng)(void *, unsigned char *, size_t), | |
1358 | void *p_rng ) | |
1359 | { | |
1360 | int ret; | |
1361 | unsigned char w, m_is_odd, p_eq_g, pre_len, i; | |
1362 | size_t d; | |
1363 | unsigned char k[COMB_MAX_D + 1]; | |
1364 | mbedtls_ecp_point *T; | |
1365 | mbedtls_mpi M, mm; | |
1366 | ||
1367 | mbedtls_mpi_init( &M ); | |
1368 | mbedtls_mpi_init( &mm ); | |
1369 | ||
1370 | /* we need N to be odd to trnaform m in an odd number, check now */ | |
1371 | if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) | |
1372 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
1373 | ||
1374 | /* | |
1375 | * Minimize the number of multiplications, that is minimize | |
1376 | * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) | |
1377 | * (see costs of the various parts, with 1S = 1M) | |
1378 | */ | |
1379 | w = grp->nbits >= 384 ? 5 : 4; | |
1380 | ||
1381 | /* | |
1382 | * If P == G, pre-compute a bit more, since this may be re-used later. | |
1383 | * Just adding one avoids upping the cost of the first mul too much, | |
1384 | * and the memory cost too. | |
1385 | */ | |
1386 | #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 | |
1387 | p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && | |
1388 | mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); | |
1389 | if( p_eq_g ) | |
1390 | w++; | |
1391 | #else | |
1392 | p_eq_g = 0; | |
1393 | #endif | |
1394 | ||
1395 | /* | |
1396 | * Make sure w is within bounds. | |
1397 | * (The last test is useful only for very small curves in the test suite.) | |
1398 | */ | |
1399 | if( w > MBEDTLS_ECP_WINDOW_SIZE ) | |
1400 | w = MBEDTLS_ECP_WINDOW_SIZE; | |
1401 | if( w >= grp->nbits ) | |
1402 | w = 2; | |
1403 | ||
1404 | /* Other sizes that depend on w */ | |
1405 | pre_len = 1U << ( w - 1 ); | |
1406 | d = ( grp->nbits + w - 1 ) / w; | |
1407 | ||
1408 | /* | |
1409 | * Prepare precomputed points: if P == G we want to | |
1410 | * use grp->T if already initialized, or initialize it. | |
1411 | */ | |
1412 | T = p_eq_g ? grp->T : NULL; | |
1413 | ||
1414 | if( T == NULL ) | |
1415 | { | |
1416 | T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); | |
1417 | if( T == NULL ) | |
1418 | { | |
1419 | ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; | |
1420 | goto cleanup; | |
1421 | } | |
1422 | ||
1423 | MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); | |
1424 | ||
1425 | if( p_eq_g ) | |
1426 | { | |
1427 | grp->T = T; | |
1428 | grp->T_size = pre_len; | |
1429 | } | |
1430 | } | |
1431 | ||
1432 | /* | |
1433 | * Make sure M is odd (M = m or M = N - m, since N is odd) | |
1434 | * using the fact that m * P = - (N - m) * P | |
1435 | */ | |
1436 | m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); | |
1437 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); | |
1438 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); | |
1439 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); | |
1440 | ||
1441 | /* | |
1442 | * Go for comb multiplication, R = M * P | |
1443 | */ | |
1444 | ecp_comb_fixed( k, d, w, &M ); | |
1445 | MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); | |
1446 | ||
1447 | /* | |
1448 | * Now get m * P from M * P and normalize it | |
1449 | */ | |
1450 | MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); | |
1451 | MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); | |
1452 | ||
1453 | cleanup: | |
1454 | ||
1455 | /* There are two cases where T is not stored in grp: | |
1456 | * - P != G | |
1457 | * - An intermediate operation failed before setting grp->T | |
1458 | * In either case, T must be freed. | |
1459 | */ | |
1460 | if( T != NULL && T != grp->T ) | |
1461 | { | |
1462 | for( i = 0; i < pre_len; i++ ) | |
1463 | mbedtls_ecp_point_free( &T[i] ); | |
1464 | mbedtls_free( T ); | |
1465 | } | |
1466 | ||
1467 | mbedtls_mpi_free( &M ); | |
1468 | mbedtls_mpi_free( &mm ); | |
1469 | ||
1470 | if( ret != 0 ) | |
1471 | mbedtls_ecp_point_free( R ); | |
1472 | ||
1473 | return( ret ); | |
1474 | } | |
1475 | ||
1476 | #endif /* ECP_SHORTWEIERSTRASS */ | |
1477 | ||
1478 | #if defined(ECP_MONTGOMERY) | |
1479 | /* | |
1480 | * For Montgomery curves, we do all the internal arithmetic in projective | |
1481 | * coordinates. Import/export of points uses only the x coordinates, which is | |
1482 | * internaly represented as X / Z. | |
1483 | * | |
1484 | * For scalar multiplication, we'll use a Montgomery ladder. | |
1485 | */ | |
1486 | ||
1487 | /* | |
1488 | * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 | |
1489 | * Cost: 1M + 1I | |
1490 | */ | |
1491 | static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) | |
1492 | { | |
1493 | int ret; | |
1494 | ||
1495 | #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) | |
1496 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
1497 | { | |
1498 | return mbedtls_internal_ecp_normalize_mxz( grp, P ); | |
1499 | } | |
1500 | #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ | |
1501 | ||
1502 | MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); | |
1503 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); | |
1504 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); | |
1505 | ||
1506 | cleanup: | |
1507 | return( ret ); | |
1508 | } | |
1509 | ||
1510 | /* | |
1511 | * Randomize projective x/z coordinates: | |
1512 | * (X, Z) -> (l X, l Z) for random l | |
1513 | * This is sort of the reverse operation of ecp_normalize_mxz(). | |
1514 | * | |
1515 | * This countermeasure was first suggested in [2]. | |
1516 | * Cost: 2M | |
1517 | */ | |
1518 | static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, | |
1519 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
1520 | { | |
1521 | int ret; | |
1522 | mbedtls_mpi l; | |
1523 | size_t p_size; | |
1524 | int count = 0; | |
1525 | ||
1526 | #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) | |
1527 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
1528 | { | |
1529 | return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); | |
1530 | } | |
1531 | #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ | |
1532 | ||
1533 | p_size = ( grp->pbits + 7 ) / 8; | |
1534 | mbedtls_mpi_init( &l ); | |
1535 | ||
1536 | /* Generate l such that 1 < l < p */ | |
1537 | do | |
1538 | { | |
1539 | MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); | |
1540 | ||
1541 | while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) | |
1542 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); | |
1543 | ||
1544 | if( count++ > 10 ) | |
1545 | return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); | |
1546 | } | |
1547 | while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); | |
1548 | ||
1549 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); | |
1550 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); | |
1551 | ||
1552 | cleanup: | |
1553 | mbedtls_mpi_free( &l ); | |
1554 | ||
1555 | return( ret ); | |
1556 | } | |
1557 | ||
1558 | /* | |
1559 | * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), | |
1560 | * for Montgomery curves in x/z coordinates. | |
1561 | * | |
1562 | * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 | |
1563 | * with | |
1564 | * d = X1 | |
1565 | * P = (X2, Z2) | |
1566 | * Q = (X3, Z3) | |
1567 | * R = (X4, Z4) | |
1568 | * S = (X5, Z5) | |
1569 | * and eliminating temporary variables tO, ..., t4. | |
1570 | * | |
1571 | * Cost: 5M + 4S | |
1572 | */ | |
1573 | static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, | |
1574 | mbedtls_ecp_point *R, mbedtls_ecp_point *S, | |
1575 | const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, | |
1576 | const mbedtls_mpi *d ) | |
1577 | { | |
1578 | int ret; | |
1579 | mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; | |
1580 | ||
1581 | #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) | |
1582 | if ( mbedtls_internal_ecp_grp_capable( grp ) ) | |
1583 | { | |
1584 | return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); | |
1585 | } | |
1586 | #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ | |
1587 | ||
1588 | mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); | |
1589 | mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); | |
1590 | mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); | |
1591 | ||
1592 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); | |
1593 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); | |
1594 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); | |
1595 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); | |
1596 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); | |
1597 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); | |
1598 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); | |
1599 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); | |
1600 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); | |
1601 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); | |
1602 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); | |
1603 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); | |
1604 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); | |
1605 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); | |
1606 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); | |
1607 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); | |
1608 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); | |
1609 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); | |
1610 | ||
1611 | cleanup: | |
1612 | mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); | |
1613 | mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); | |
1614 | mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); | |
1615 | ||
1616 | return( ret ); | |
1617 | } | |
1618 | ||
1619 | /* | |
1620 | * Multiplication with Montgomery ladder in x/z coordinates, | |
1621 | * for curves in Montgomery form | |
1622 | */ | |
1623 | static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1624 | const mbedtls_mpi *m, const mbedtls_ecp_point *P, | |
1625 | int (*f_rng)(void *, unsigned char *, size_t), | |
1626 | void *p_rng ) | |
1627 | { | |
1628 | int ret; | |
1629 | size_t i; | |
1630 | unsigned char b; | |
1631 | mbedtls_ecp_point RP; | |
1632 | mbedtls_mpi PX; | |
1633 | ||
1634 | mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); | |
1635 | ||
1636 | /* Save PX and read from P before writing to R, in case P == R */ | |
1637 | MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); | |
1638 | MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); | |
1639 | ||
1640 | /* Set R to zero in modified x/z coordinates */ | |
1641 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); | |
1642 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); | |
1643 | mbedtls_mpi_free( &R->Y ); | |
1644 | ||
1645 | /* RP.X might be sligtly larger than P, so reduce it */ | |
1646 | MOD_ADD( RP.X ); | |
1647 | ||
1648 | /* Randomize coordinates of the starting point */ | |
1649 | if( f_rng != NULL ) | |
1650 | MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); | |
1651 | ||
1652 | /* Loop invariant: R = result so far, RP = R + P */ | |
1653 | i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ | |
1654 | while( i-- > 0 ) | |
1655 | { | |
1656 | b = mbedtls_mpi_get_bit( m, i ); | |
1657 | /* | |
1658 | * if (b) R = 2R + P else R = 2R, | |
1659 | * which is: | |
1660 | * if (b) double_add( RP, R, RP, R ) | |
1661 | * else double_add( R, RP, R, RP ) | |
1662 | * but using safe conditional swaps to avoid leaks | |
1663 | */ | |
1664 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); | |
1665 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); | |
1666 | MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); | |
1667 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); | |
1668 | MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); | |
1669 | } | |
1670 | ||
1671 | MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); | |
1672 | ||
1673 | cleanup: | |
1674 | mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); | |
1675 | ||
1676 | return( ret ); | |
1677 | } | |
1678 | ||
1679 | #endif /* ECP_MONTGOMERY */ | |
1680 | ||
1681 | /* | |
1682 | * Multiplication R = m * P | |
1683 | */ | |
1684 | int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1685 | const mbedtls_mpi *m, const mbedtls_ecp_point *P, | |
1686 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
1687 | { | |
1688 | int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; | |
1689 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1690 | char is_grp_capable = 0; | |
1691 | #endif | |
1692 | ||
1693 | /* Common sanity checks */ | |
1694 | if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) | |
1695 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
1696 | ||
1697 | if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || | |
1698 | ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) | |
1699 | return( ret ); | |
1700 | ||
1701 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1702 | if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) | |
1703 | { | |
1704 | MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); | |
1705 | } | |
1706 | ||
1707 | #endif /* MBEDTLS_ECP_INTERNAL_ALT */ | |
1708 | #if defined(ECP_MONTGOMERY) | |
1709 | if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) | |
1710 | ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); | |
1711 | ||
1712 | #endif | |
1713 | #if defined(ECP_SHORTWEIERSTRASS) | |
1714 | if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) | |
1715 | ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); | |
1716 | ||
1717 | #endif | |
1718 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1719 | cleanup: | |
1720 | ||
1721 | if ( is_grp_capable ) | |
1722 | { | |
1723 | mbedtls_internal_ecp_free( grp ); | |
1724 | } | |
1725 | ||
1726 | #endif /* MBEDTLS_ECP_INTERNAL_ALT */ | |
1727 | return( ret ); | |
1728 | } | |
1729 | ||
1730 | #if defined(ECP_SHORTWEIERSTRASS) | |
1731 | /* | |
1732 | * Check that an affine point is valid as a public key, | |
1733 | * short weierstrass curves (SEC1 3.2.3.1) | |
1734 | */ | |
1735 | static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) | |
1736 | { | |
1737 | int ret; | |
1738 | mbedtls_mpi YY, RHS; | |
1739 | ||
1740 | /* pt coordinates must be normalized for our checks */ | |
1741 | if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || | |
1742 | mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || | |
1743 | mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || | |
1744 | mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) | |
1745 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1746 | ||
1747 | mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); | |
1748 | ||
1749 | /* | |
1750 | * YY = Y^2 | |
1751 | * RHS = X (X^2 + A) + B = X^3 + A X + B | |
1752 | */ | |
1753 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); | |
1754 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); | |
1755 | ||
1756 | /* Special case for A = -3 */ | |
1757 | if( grp->A.p == NULL ) | |
1758 | { | |
1759 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); | |
1760 | } | |
1761 | else | |
1762 | { | |
1763 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); | |
1764 | } | |
1765 | ||
1766 | MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); | |
1767 | MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); | |
1768 | ||
1769 | if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) | |
1770 | ret = MBEDTLS_ERR_ECP_INVALID_KEY; | |
1771 | ||
1772 | cleanup: | |
1773 | ||
1774 | mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); | |
1775 | ||
1776 | return( ret ); | |
1777 | } | |
1778 | #endif /* ECP_SHORTWEIERSTRASS */ | |
1779 | ||
1780 | /* | |
1781 | * R = m * P with shortcuts for m == 1 and m == -1 | |
1782 | * NOT constant-time - ONLY for short Weierstrass! | |
1783 | */ | |
1784 | static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, | |
1785 | mbedtls_ecp_point *R, | |
1786 | const mbedtls_mpi *m, | |
1787 | const mbedtls_ecp_point *P ) | |
1788 | { | |
1789 | int ret; | |
1790 | ||
1791 | if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) | |
1792 | { | |
1793 | MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); | |
1794 | } | |
1795 | else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) | |
1796 | { | |
1797 | MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); | |
1798 | if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) | |
1799 | MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); | |
1800 | } | |
1801 | else | |
1802 | { | |
1803 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); | |
1804 | } | |
1805 | ||
1806 | cleanup: | |
1807 | return( ret ); | |
1808 | } | |
1809 | ||
1810 | /* | |
1811 | * Linear combination | |
1812 | * NOT constant-time | |
1813 | */ | |
1814 | int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, | |
1815 | const mbedtls_mpi *m, const mbedtls_ecp_point *P, | |
1816 | const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) | |
1817 | { | |
1818 | int ret; | |
1819 | mbedtls_ecp_point mP; | |
1820 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1821 | char is_grp_capable = 0; | |
1822 | #endif | |
1823 | ||
1824 | if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) | |
1825 | return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); | |
1826 | ||
1827 | mbedtls_ecp_point_init( &mP ); | |
1828 | ||
1829 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); | |
1830 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); | |
1831 | ||
1832 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1833 | if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) | |
1834 | { | |
1835 | MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); | |
1836 | } | |
1837 | ||
1838 | #endif /* MBEDTLS_ECP_INTERNAL_ALT */ | |
1839 | MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); | |
1840 | MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); | |
1841 | ||
1842 | cleanup: | |
1843 | ||
1844 | #if defined(MBEDTLS_ECP_INTERNAL_ALT) | |
1845 | if ( is_grp_capable ) | |
1846 | { | |
1847 | mbedtls_internal_ecp_free( grp ); | |
1848 | } | |
1849 | ||
1850 | #endif /* MBEDTLS_ECP_INTERNAL_ALT */ | |
1851 | mbedtls_ecp_point_free( &mP ); | |
1852 | ||
1853 | return( ret ); | |
1854 | } | |
1855 | ||
1856 | ||
1857 | #if defined(ECP_MONTGOMERY) | |
1858 | /* | |
1859 | * Check validity of a public key for Montgomery curves with x-only schemes | |
1860 | */ | |
1861 | static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) | |
1862 | { | |
1863 | /* [Curve25519 p. 5] Just check X is the correct number of bytes */ | |
1864 | /* Allow any public value, if it's too big then we'll just reduce it mod p | |
1865 | * (RFC 7748 sec. 5 para. 3). */ | |
1866 | if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) | |
1867 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1868 | ||
1869 | return( 0 ); | |
1870 | } | |
1871 | #endif /* ECP_MONTGOMERY */ | |
1872 | ||
1873 | /* | |
1874 | * Check that a point is valid as a public key | |
1875 | */ | |
1876 | int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) | |
1877 | { | |
1878 | /* Must use affine coordinates */ | |
1879 | if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) | |
1880 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1881 | ||
1882 | #if defined(ECP_MONTGOMERY) | |
1883 | if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) | |
1884 | return( ecp_check_pubkey_mx( grp, pt ) ); | |
1885 | #endif | |
1886 | #if defined(ECP_SHORTWEIERSTRASS) | |
1887 | if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) | |
1888 | return( ecp_check_pubkey_sw( grp, pt ) ); | |
1889 | #endif | |
1890 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
1891 | } | |
1892 | ||
1893 | /* | |
1894 | * Check that an mbedtls_mpi is valid as a private key | |
1895 | */ | |
1896 | int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) | |
1897 | { | |
1898 | #if defined(ECP_MONTGOMERY) | |
1899 | if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) | |
1900 | { | |
1901 | /* see RFC 7748 sec. 5 para. 5 */ | |
1902 | if( mbedtls_mpi_get_bit( d, 0 ) != 0 || | |
1903 | mbedtls_mpi_get_bit( d, 1 ) != 0 || | |
1904 | mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ | |
1905 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1906 | ||
1907 | /* see [Curve25519] page 5 */ | |
1908 | if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) | |
1909 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1910 | ||
1911 | return( 0 ); | |
1912 | } | |
1913 | #endif /* ECP_MONTGOMERY */ | |
1914 | #if defined(ECP_SHORTWEIERSTRASS) | |
1915 | if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) | |
1916 | { | |
1917 | /* see SEC1 3.2 */ | |
1918 | if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || | |
1919 | mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) | |
1920 | return( MBEDTLS_ERR_ECP_INVALID_KEY ); | |
1921 | else | |
1922 | return( 0 ); | |
1923 | } | |
1924 | #endif /* ECP_SHORTWEIERSTRASS */ | |
1925 | ||
1926 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
1927 | } | |
1928 | ||
1929 | /* | |
1930 | * Generate a keypair with configurable base point | |
1931 | */ | |
1932 | int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, | |
1933 | const mbedtls_ecp_point *G, | |
1934 | mbedtls_mpi *d, mbedtls_ecp_point *Q, | |
1935 | int (*f_rng)(void *, unsigned char *, size_t), | |
1936 | void *p_rng ) | |
1937 | { | |
1938 | int ret; | |
1939 | size_t n_size = ( grp->nbits + 7 ) / 8; | |
1940 | ||
1941 | #if defined(ECP_MONTGOMERY) | |
1942 | if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) | |
1943 | { | |
1944 | /* [M225] page 5 */ | |
1945 | size_t b; | |
1946 | ||
1947 | do { | |
1948 | MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); | |
1949 | } while( mbedtls_mpi_bitlen( d ) == 0); | |
1950 | ||
1951 | /* Make sure the most significant bit is nbits */ | |
1952 | b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ | |
1953 | if( b > grp->nbits ) | |
1954 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); | |
1955 | else | |
1956 | MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); | |
1957 | ||
1958 | /* Make sure the last two bits are unset for Curve448, three bits for | |
1959 | Curve25519 */ | |
1960 | MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); | |
1961 | MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); | |
1962 | if( grp->nbits == 254 ) | |
1963 | { | |
1964 | MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); | |
1965 | } | |
1966 | } | |
1967 | else | |
1968 | #endif /* ECP_MONTGOMERY */ | |
1969 | #if defined(ECP_SHORTWEIERSTRASS) | |
1970 | if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) | |
1971 | { | |
1972 | /* SEC1 3.2.1: Generate d such that 1 <= n < N */ | |
1973 | int count = 0; | |
1974 | ||
1975 | /* | |
1976 | * Match the procedure given in RFC 6979 (deterministic ECDSA): | |
1977 | * - use the same byte ordering; | |
1978 | * - keep the leftmost nbits bits of the generated octet string; | |
1979 | * - try until result is in the desired range. | |
1980 | * This also avoids any biais, which is especially important for ECDSA. | |
1981 | */ | |
1982 | do | |
1983 | { | |
1984 | MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); | |
1985 | MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); | |
1986 | ||
1987 | /* | |
1988 | * Each try has at worst a probability 1/2 of failing (the msb has | |
1989 | * a probability 1/2 of being 0, and then the result will be < N), | |
1990 | * so after 30 tries failure probability is a most 2**(-30). | |
1991 | * | |
1992 | * For most curves, 1 try is enough with overwhelming probability, | |
1993 | * since N starts with a lot of 1s in binary, but some curves | |
1994 | * such as secp224k1 are actually very close to the worst case. | |
1995 | */ | |
1996 | if( ++count > 30 ) | |
1997 | return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); | |
1998 | } | |
1999 | while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || | |
2000 | mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); | |
2001 | } | |
2002 | else | |
2003 | #endif /* ECP_SHORTWEIERSTRASS */ | |
2004 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
2005 | ||
2006 | cleanup: | |
2007 | if( ret != 0 ) | |
2008 | return( ret ); | |
2009 | ||
2010 | return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); | |
2011 | } | |
2012 | ||
2013 | /* | |
2014 | * Generate key pair, wrapper for conventional base point | |
2015 | */ | |
2016 | int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, | |
2017 | mbedtls_mpi *d, mbedtls_ecp_point *Q, | |
2018 | int (*f_rng)(void *, unsigned char *, size_t), | |
2019 | void *p_rng ) | |
2020 | { | |
2021 | return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); | |
2022 | } | |
2023 | ||
2024 | /* | |
2025 | * Generate a keypair, prettier wrapper | |
2026 | */ | |
2027 | int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, | |
2028 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
2029 | { | |
2030 | int ret; | |
2031 | ||
2032 | if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) | |
2033 | return( ret ); | |
2034 | ||
2035 | return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); | |
2036 | } | |
2037 | ||
2038 | /* | |
2039 | * Check a public-private key pair | |
2040 | */ | |
2041 | int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) | |
2042 | { | |
2043 | int ret; | |
2044 | mbedtls_ecp_point Q; | |
2045 | mbedtls_ecp_group grp; | |
2046 | ||
2047 | if( pub->grp.id == MBEDTLS_ECP_DP_NONE || | |
2048 | pub->grp.id != prv->grp.id || | |
2049 | mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || | |
2050 | mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || | |
2051 | mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) | |
2052 | { | |
2053 | return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); | |
2054 | } | |
2055 | ||
2056 | mbedtls_ecp_point_init( &Q ); | |
2057 | mbedtls_ecp_group_init( &grp ); | |
2058 | ||
2059 | /* mbedtls_ecp_mul() needs a non-const group... */ | |
2060 | mbedtls_ecp_group_copy( &grp, &prv->grp ); | |
2061 | ||
2062 | /* Also checks d is valid */ | |
2063 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); | |
2064 | ||
2065 | if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || | |
2066 | mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || | |
2067 | mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) | |
2068 | { | |
2069 | ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; | |
2070 | goto cleanup; | |
2071 | } | |
2072 | ||
2073 | cleanup: | |
2074 | mbedtls_ecp_point_free( &Q ); | |
2075 | mbedtls_ecp_group_free( &grp ); | |
2076 | ||
2077 | return( ret ); | |
2078 | } | |
2079 | ||
2080 | #if defined(MBEDTLS_SELF_TEST) | |
2081 | ||
2082 | /* | |
2083 | * Checkup routine | |
2084 | */ | |
2085 | int mbedtls_ecp_self_test( int verbose ) | |
2086 | { | |
2087 | int ret; | |
2088 | size_t i; | |
2089 | mbedtls_ecp_group grp; | |
2090 | mbedtls_ecp_point R, P; | |
2091 | mbedtls_mpi m; | |
2092 | unsigned long add_c_prev, dbl_c_prev, mul_c_prev; | |
2093 | /* exponents especially adapted for secp192r1 */ | |
2094 | const char *exponents[] = | |
2095 | { | |
2096 | "000000000000000000000000000000000000000000000001", /* one */ | |
2097 | "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ | |
2098 | "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ | |
2099 | "400000000000000000000000000000000000000000000000", /* one and zeros */ | |
2100 | "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ | |
2101 | "555555555555555555555555555555555555555555555555", /* 101010... */ | |
2102 | }; | |
2103 | ||
2104 | mbedtls_ecp_group_init( &grp ); | |
2105 | mbedtls_ecp_point_init( &R ); | |
2106 | mbedtls_ecp_point_init( &P ); | |
2107 | mbedtls_mpi_init( &m ); | |
2108 | ||
2109 | /* Use secp192r1 if available, or any available curve */ | |
2110 | #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) | |
2111 | MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); | |
2112 | #else | |
2113 | MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); | |
2114 | #endif | |
2115 | ||
2116 | if( verbose != 0 ) | |
2117 | mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); | |
2118 | ||
2119 | /* Do a dummy multiplication first to trigger precomputation */ | |
2120 | MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); | |
2121 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); | |
2122 | ||
2123 | add_count = 0; | |
2124 | dbl_count = 0; | |
2125 | mul_count = 0; | |
2126 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); | |
2127 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); | |
2128 | ||
2129 | for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) | |
2130 | { | |
2131 | add_c_prev = add_count; | |
2132 | dbl_c_prev = dbl_count; | |
2133 | mul_c_prev = mul_count; | |
2134 | add_count = 0; | |
2135 | dbl_count = 0; | |
2136 | mul_count = 0; | |
2137 | ||
2138 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); | |
2139 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); | |
2140 | ||
2141 | if( add_count != add_c_prev || | |
2142 | dbl_count != dbl_c_prev || | |
2143 | mul_count != mul_c_prev ) | |
2144 | { | |
2145 | if( verbose != 0 ) | |
2146 | mbedtls_printf( "failed (%u)\n", (unsigned int) i ); | |
2147 | ||
2148 | ret = 1; | |
2149 | goto cleanup; | |
2150 | } | |
2151 | } | |
2152 | ||
2153 | if( verbose != 0 ) | |
2154 | mbedtls_printf( "passed\n" ); | |
2155 | ||
2156 | if( verbose != 0 ) | |
2157 | mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); | |
2158 | /* We computed P = 2G last time, use it */ | |
2159 | ||
2160 | add_count = 0; | |
2161 | dbl_count = 0; | |
2162 | mul_count = 0; | |
2163 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); | |
2164 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); | |
2165 | ||
2166 | for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) | |
2167 | { | |
2168 | add_c_prev = add_count; | |
2169 | dbl_c_prev = dbl_count; | |
2170 | mul_c_prev = mul_count; | |
2171 | add_count = 0; | |
2172 | dbl_count = 0; | |
2173 | mul_count = 0; | |
2174 | ||
2175 | MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); | |
2176 | MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); | |
2177 | ||
2178 | if( add_count != add_c_prev || | |
2179 | dbl_count != dbl_c_prev || | |
2180 | mul_count != mul_c_prev ) | |
2181 | { | |
2182 | if( verbose != 0 ) | |
2183 | mbedtls_printf( "failed (%u)\n", (unsigned int) i ); | |
2184 | ||
2185 | ret = 1; | |
2186 | goto cleanup; | |
2187 | } | |
2188 | } | |
2189 | ||
2190 | if( verbose != 0 ) | |
2191 | mbedtls_printf( "passed\n" ); | |
2192 | ||
2193 | cleanup: | |
2194 | ||
2195 | if( ret < 0 && verbose != 0 ) | |
2196 | mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); | |
2197 | ||
2198 | mbedtls_ecp_group_free( &grp ); | |
2199 | mbedtls_ecp_point_free( &R ); | |
2200 | mbedtls_ecp_point_free( &P ); | |
2201 | mbedtls_mpi_free( &m ); | |
2202 | ||
2203 | if( verbose != 0 ) | |
2204 | mbedtls_printf( "\n" ); | |
2205 | ||
2206 | return( ret ); | |
2207 | } | |
2208 | ||
2209 | #endif /* MBEDTLS_SELF_TEST */ | |
2210 | ||
2211 | #endif /* !MBEDTLS_ECP_ALT */ | |
2212 | ||
2213 | #endif /* MBEDTLS_ECP_C */ |