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