blob: ee3d6bfcce6d794e77e4db47d3b3a1c19567b187 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
2 * Elliptic curves over GF(p)
3 *
4 * Copyright (C) 2012, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26/*
27 * References:
28 *
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010029 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010030 * Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
31 */
32
33#include "polarssl/config.h"
34
35#if defined(POLARSSL_ECP_C)
36
37#include "polarssl/ecp.h"
38
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +010039/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +010040 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +010041 */
42void ecp_point_init( ecp_point *pt )
43{
44 if( pt == NULL )
45 return;
46
47 pt->is_zero = 1;
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +010048 mpi_init( &pt->X );
49 mpi_init( &pt->Y );
50}
51
52/*
53 * Initialize (the components of) a group
54 */
55void ecp_group_init( ecp_group *grp )
56{
57 if( grp == NULL )
58 return;
59
60 mpi_init( &grp->P );
61 mpi_init( &grp->B );
62 ecp_point_init( &grp->G );
63 mpi_init( &grp->N );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +010064}
65
66/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +010067 * Unallocate (the components of) a point
68 */
69void ecp_point_free( ecp_point *pt )
70{
71 if( pt == NULL )
72 return;
73
Manuel Pégourié-Gonnard5179e462012-10-31 19:37:54 +010074 pt->is_zero = 1;
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +010075 mpi_free( &( pt->X ) );
76 mpi_free( &( pt->Y ) );
77}
78
79/*
80 * Unallocate (the components of) a group
81 */
82void ecp_group_free( ecp_group *grp )
83{
84 if( grp == NULL )
85 return;
86
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010087 mpi_free( &grp->P );
88 mpi_free( &grp->B );
89 ecp_point_free( &grp->G );
90 mpi_free( &grp->N );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +010091}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010092
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +010093/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +010094 * Set point to zero
95 */
96void ecp_set_zero( ecp_point *pt )
97{
98 pt->is_zero = 1;
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +010099 mpi_free( &pt->X );
100 mpi_free( &pt->Y );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100101}
102
103/*
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100104 * Copy the contents of Q into P
105 */
106int ecp_copy( ecp_point *P, const ecp_point *Q )
107{
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100108 int ret = 0;
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100109
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100110 if( Q->is_zero ) {
111 ecp_set_zero( P );
112 return( ret );
113 }
114
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100115 P->is_zero = Q->is_zero;
116 MPI_CHK( mpi_copy( &P->X, &Q->X ) );
117 MPI_CHK( mpi_copy( &P->Y, &Q->Y ) );
118
119cleanup:
120 return( ret );
121}
Manuel Pégourié-Gonnard5179e462012-10-31 19:37:54 +0100122
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100123/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100124 * Import a non-zero point from ASCII strings
125 */
126int ecp_point_read_string( ecp_point *P, int radix,
127 const char *x, const char *y )
128{
129 int ret = 0;
130
131 P->is_zero = 0;
132 MPI_CHK( mpi_read_string( &P->X, radix, x ) );
133 MPI_CHK( mpi_read_string( &P->Y, radix, y ) );
134
135cleanup:
136 return( ret );
137}
138
139/*
140 * Import an ECP group from ASCII strings
141 */
142int ecp_group_read_string( ecp_group *grp, int radix,
143 const char *p, const char *b,
144 const char *gx, const char *gy, const char *n)
145{
146 int ret = 0;
147
148 MPI_CHK( mpi_read_string( &grp->P, radix, p ) );
149 MPI_CHK( mpi_read_string( &grp->B, radix, b ) );
150 MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) );
151 MPI_CHK( mpi_read_string( &grp->N, radix, n ) );
152
153cleanup:
154 return( ret );
155}
156
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100157/*
158 * Set a group using well-known domain parameters
159 */
160int ecp_use_known_dp( ecp_group *grp, size_t index )
161{
162 switch( index )
163 {
164 case POLARSSL_ECP_DP_SECP192R1:
165 return( ecp_group_read_string( grp, 16,
166 POLARSSL_ECP_SECP192R1_P,
167 POLARSSL_ECP_SECP192R1_B,
168 POLARSSL_ECP_SECP192R1_GX,
169 POLARSSL_ECP_SECP192R1_GY,
170 POLARSSL_ECP_SECP192R1_N )
171 );
172 case POLARSSL_ECP_DP_SECP224R1:
173 return( ecp_group_read_string( grp, 16,
174 POLARSSL_ECP_SECP224R1_P,
175 POLARSSL_ECP_SECP224R1_B,
176 POLARSSL_ECP_SECP224R1_GX,
177 POLARSSL_ECP_SECP224R1_GY,
178 POLARSSL_ECP_SECP224R1_N )
179 );
180 case POLARSSL_ECP_DP_SECP256R1:
181 return( ecp_group_read_string( grp, 16,
182 POLARSSL_ECP_SECP256R1_P,
183 POLARSSL_ECP_SECP256R1_B,
184 POLARSSL_ECP_SECP256R1_GX,
185 POLARSSL_ECP_SECP256R1_GY,
186 POLARSSL_ECP_SECP256R1_N )
187 );
188 case POLARSSL_ECP_DP_SECP384R1:
189 return( ecp_group_read_string( grp, 16,
190 POLARSSL_ECP_SECP384R1_P,
191 POLARSSL_ECP_SECP384R1_B,
192 POLARSSL_ECP_SECP384R1_GX,
193 POLARSSL_ECP_SECP384R1_GY,
194 POLARSSL_ECP_SECP384R1_N )
195 );
196 case POLARSSL_ECP_DP_SECP521R1:
197 return( ecp_group_read_string( grp, 16,
198 POLARSSL_ECP_SECP521R1_P,
199 POLARSSL_ECP_SECP521R1_B,
200 POLARSSL_ECP_SECP521R1_GX,
201 POLARSSL_ECP_SECP521R1_GY,
202 POLARSSL_ECP_SECP521R1_N )
203 );
204 }
205
206 return( POLARSSL_ERR_ECP_GENERIC );
207}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100208
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100209/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100210 * Addition: R = P + Q, generic case (P != Q, P != 0, Q != 0, R != 0)
211 * Cf SEC1 v2 p. 7, item 4
212 */
213static int ecp_add_generic( const ecp_group *grp, ecp_point *R,
214 const ecp_point *P, const ecp_point *Q )
215{
216 int ret = 0;
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100217 mpi DX, DY, K, L, LL, X, Y;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100218
219 mpi_init( &DX ); mpi_init( &DY ); mpi_init( &K ); mpi_init( &L );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100220 mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100221
222 /*
223 * L = (Q.Y - P.Y) / (Q.X - P.X) mod p
224 */
225 MPI_CHK( mpi_sub_mpi( &DY, &Q->Y, &P->Y ) );
226 MPI_CHK( mpi_sub_mpi( &DX, &Q->X, &P->X ) );
227 MPI_CHK( mpi_inv_mod( &K, &DX, &grp->P ) );
228 MPI_CHK( mpi_mul_mpi( &K, &K, &DY ) );
229 MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) );
230
231 /*
232 * LL = L^2 mod p
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100233 */
234 MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) );
235 MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100236
237 /*
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100238 * X = L^2 - P.X - Q.X
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100239 */
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100240 MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) );
241 MPI_CHK( mpi_sub_mpi( &X, &X, &Q->X ) );
242
243 /*
244 * Y = L * (P.X - X) - P.Y
245 */
246 MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100247 MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) );
248 MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) );
249
250 /*
251 * R = (X mod p, Y mod p)
252 */
253 R->is_zero = 0;
254 MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) );
255 MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) );
256
257cleanup:
258
259 mpi_free( &DX ); mpi_free( &DY ); mpi_free( &K ); mpi_free( &L );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100260 mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100261
262 return( ret );
263}
264
265/*
266 * Doubling: R = 2 * P, generic case (P != 0, R != 0)
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100267 * Cf SEC1 v2 p. 7, item 5
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100268 */
269static int ecp_double_generic( const ecp_group *grp, ecp_point *R,
270 const ecp_point *P )
271{
272 int ret = 0;
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100273 mpi LN, LD, K, L, LL, X, Y;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100274
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100275 mpi_init( &LN ); mpi_init( &LD ); mpi_init( &K ); mpi_init( &L );
276 mpi_init( &LL ); mpi_init( &X ); mpi_init( &Y );
277
278 /*
279 * L = 3 (P.X - 1) (P.X + 1) / (2 P.Y) mod p
280 */
281 MPI_CHK( mpi_copy( &LD, &P->Y ) );
282 MPI_CHK( mpi_shift_l( &LD, 1 ) );
283 MPI_CHK( mpi_inv_mod( &K, &LD, &grp->P ) );
284 MPI_CHK( mpi_mul_int( &K, &K, 3 ) );
285 MPI_CHK( mpi_sub_int( &LN, &P->X, 1 ) );
286 MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) );
287 MPI_CHK( mpi_add_int( &LN, &P->X, 1 ) );
288 MPI_CHK( mpi_mul_mpi( &K, &K, &LN ) );
289 MPI_CHK( mpi_mod_mpi( &L, &K, &grp->P ) );
290
291 /*
292 * LL = L^2 mod p
293 */
294 MPI_CHK( mpi_mul_mpi( &LL, &L, &L ) );
295 MPI_CHK( mpi_mod_mpi( &LL, &LL, &grp->P ) );
296
297 /*
298 * X = L^2 - 2 * P.X
299 */
300 MPI_CHK( mpi_sub_mpi( &X, &LL, &P->X ) );
301 MPI_CHK( mpi_sub_mpi( &X, &X, &P->X ) );
302
303 /*
304 * Y = L * (P.X - X) - P.Y
305 */
306 MPI_CHK( mpi_sub_mpi( &Y, &P->X, &X) );
307 MPI_CHK( mpi_mul_mpi( &Y, &Y, &L ) );
308 MPI_CHK( mpi_sub_mpi( &Y, &Y, &P->Y ) );
309
310 /*
311 * R = (X mod p, Y mod p)
312 */
313 R->is_zero = 0;
314 MPI_CHK( mpi_mod_mpi( &R->X, &X, &grp->P ) );
315 MPI_CHK( mpi_mod_mpi( &R->Y, &Y, &grp->P ) );
316
317cleanup:
318
Manuel Pégourié-Gonnardb4ab8a82012-11-06 18:13:32 +0100319 mpi_free( &LN ); mpi_free( &LD ); mpi_free( &K ); mpi_free( &L );
320 mpi_free( &LL ); mpi_free( &X ); mpi_free( &Y );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100321
322 return( ret );
323}
324
325/*
326 * Addition: R = P + Q, cf p. 7 of SEC1 v2
327 */
328int ecp_add( const ecp_group *grp, ecp_point *R,
329 const ecp_point *P, const ecp_point *Q )
330{
331 int ret = 0;
332
333 if( P->is_zero )
334 {
335 ret = ecp_copy( R, Q );
336 }
337 else if( Q->is_zero )
338 {
339 ret = ecp_copy( R, P );
340 }
341 else if( mpi_cmp_mpi( &P->X, &Q->X ) != 0 )
342 {
343 ret = ecp_add_generic( grp, R, P, Q );
344 }
345 else if( mpi_cmp_int( &P->Y, 0 ) == 0 ||
346 mpi_cmp_mpi( &P->Y, &Q->Y ) != 0 )
347 {
348 ecp_set_zero( R );
349 }
350 else
351 {
352 /*
353 * P == Q
354 */
355 ret = ecp_double_generic( grp, R, P );
356 }
357
358 return ret;
359}
360
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100361/*
362 * Integer multiplication: R = m * P
363 * Using Montgomery's Ladder to avoid leaking information about m
364 */
365int ecp_mul( const ecp_group *grp, ecp_point *R,
366 const mpi *m, const ecp_point *P )
367{
368 int ret = 0;
369 size_t pos;
370 ecp_point A, B;
371
372 ecp_point_init( &A ); ecp_point_init( &B );
373
374 /*
375 * The general method works only for m >= 2
376 */
377 if( mpi_cmp_int( m, 0 ) == 0 ) {
378 ecp_set_zero( R );
379 goto cleanup;
380 }
381
382 if( mpi_cmp_int( m, 1 ) == 0 ) {
383 MPI_CHK( ecp_copy( R, P ) );
384 goto cleanup;
385 }
386
387 MPI_CHK( ecp_copy( &A, P ) );
388 MPI_CHK( ecp_add( grp, &B, P, P ) );
389
390 for( pos = mpi_msb( m ) - 2; ; pos-- )
391 {
392 if( mpi_get_bit( m, pos ) == 0 )
393 {
394 MPI_CHK( ecp_add( grp, &B, &A, &B ) );
395 MPI_CHK( ecp_add( grp, &A, &A, &A ) ) ;
396 }
397 else
398 {
399 MPI_CHK( ecp_add( grp, &A, &A, &B ) );
400 MPI_CHK( ecp_add( grp, &B, &B, &B ) ) ;
401 }
402
403 if( pos == 0 )
404 break;
405 }
406
407 MPI_CHK( ecp_copy( R, &A ) );
408
409cleanup:
410
411 ecp_point_free( &A ); ecp_point_free( &B );
412
413 return( ret );
414}
415
416
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100417#if defined(POLARSSL_SELF_TEST)
418
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100419#include "polarssl/error.h"
420
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100421/*
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100422 * Return true iff P and Q are the same point
423 */
424static int ecp_point_eq( const ecp_point *P, const ecp_point *Q )
425{
426 if( P->is_zero || Q->is_zero )
427 return( P->is_zero && Q->is_zero );
428
429 return( mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
430 mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 );
431}
432
433/*
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100434 * Print a point assuming its coordinates are small
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100435 */
436static void ecp_point_print( const ecp_point *P )
437{
438 if( P->is_zero )
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100439 printf( "zero\n" );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100440 else
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100441 printf( "(%lu, %lu)\n", P->X.p[0], P->Y.p[0] );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100442}
443
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100444#define TEST_GROUP_ORDER 13
445
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100446/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100447 * Checkup routine
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100448 *
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100449 * Data for basic tests with small values gathered from
450 * http://danher6.100webspace.net/ecc/#EFp_interactivo and double-checked
451 * using Pari-GP.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100452 */
453int ecp_self_test( int verbose )
454{
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100455 int ret = 0;
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100456 unsigned i;
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100457 ecp_group grp;
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100458 ecp_point O, A, B, C, D, E, F, G, H, TMP;
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100459 ecp_point *add_tbl[][3] =
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100460 {
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100461 { &O, &O, &O }, { &O, &A, &A }, { &A, &O, &A },
462 { &A, &A, &O }, { &B, &C, &O }, { &C, &B, &O },
463 { &A, &D, &E }, { &D, &A, &E },
464 { &B, &D, &F }, { &D, &B, &F },
465 { &D, &D, &G }, { &B, &B, &H },
466 };
467 mpi m;
468 ecp_point mul_tbl[TEST_GROUP_ORDER + 1];
469 char *mul_tbl_s[TEST_GROUP_ORDER - 1][2] =
470 {
471 { "17", "42" },
472 { "20", "01" },
473 { "14", "11" },
474 { "34", "33" },
475 { "21", "32" },
476 { "27", "30" },
477 { "27", "17" },
478 { "21", "15" },
479 { "34", "14" },
480 { "14", "36" },
481 { "20", "46" },
482 { "17", "05" },
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100483 };
484
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100485 ecp_group_init( &grp );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100486
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100487 ecp_point_init( &O ); ecp_point_init( &A ); ecp_point_init( &B );
488 ecp_point_init( &C ); ecp_point_init( &D ); ecp_point_init( &E );
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100489 ecp_point_init( &F ); ecp_point_init( &G ); ecp_point_init( &H );
490 ecp_point_init( &TMP );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100491
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100492 mpi_init( &m );
493
494 for( i = 0; i <= TEST_GROUP_ORDER; i++ )
495 ecp_point_init( &mul_tbl[i] );
496
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100497 ecp_set_zero( &O );
498 MPI_CHK( ecp_group_read_string( &grp, 10, "47", "4", "17", "42", "13" ) );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100499 MPI_CHK( ecp_point_read_string( &A, 10, "13", "00" ) );
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100500 MPI_CHK( ecp_point_read_string( &B, 10, "14", "11" ) );
501 MPI_CHK( ecp_point_read_string( &C, 10, "14", "36" ) );
502 MPI_CHK( ecp_point_read_string( &D, 10, "37", "31" ) );
503 MPI_CHK( ecp_point_read_string( &E, 10, "34", "14" ) );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100504 MPI_CHK( ecp_point_read_string( &F, 10, "45", "07" ) );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100505 MPI_CHK( ecp_point_read_string( &G, 10, "21", "32" ) );
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100506 MPI_CHK( ecp_point_read_string( &H, 10, "27", "30" ) );
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100507
508 if( verbose != 0 )
509 printf( " ECP test #1 (ecp_add): " );
510
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100511 for( i = 0; i < sizeof( add_tbl ) / sizeof( add_tbl[0] ); i++ )
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100512 {
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100513 MPI_CHK( ecp_add( &grp, &TMP, add_tbl[i][0], add_tbl[i][1] ) );
514 if( ! ecp_point_eq( &TMP, add_tbl[i][2] ) )
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100515 {
516 if( verbose != 0 )
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100517 {
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100518 printf( " failed (%u)\n", i );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100519 printf( " GOT: " );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100520 ecp_point_print( &TMP );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100521 printf( " EXPECTED: " );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100522 ecp_point_print( add_tbl[i][2] );
523 }
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100524
525 return( 1 );
526 }
527 }
528
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100529 if( verbose != 0 )
Manuel Pégourié-Gonnardde532ee2012-11-06 16:10:47 +0100530 printf( "passed\n" );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100531
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100532 MPI_CHK( ecp_copy( &mul_tbl[0], &O ) );
533 for( i = 1; i <= TEST_GROUP_ORDER - 1; i++ )
534 MPI_CHK( ecp_point_read_string( &mul_tbl[i], 10,
535 mul_tbl_s[i-1][0], mul_tbl_s[i-1][1] ) );
536 MPI_CHK( ecp_copy( &mul_tbl[TEST_GROUP_ORDER], &O ) );
537
538 if( verbose != 0 )
539 printf( " ECP test #2 (ecp_mul): " );
540
541 for( i = 0; i <= TEST_GROUP_ORDER; i++ )
542 {
543 MPI_CHK( mpi_lset( &m, i ) );
544 MPI_CHK( ecp_mul( &grp, &TMP, &m, &grp.G ) );
545 if( ! ecp_point_eq( &TMP, &mul_tbl[i] ) )
546 {
547 if( verbose != 0 )
548 {
549 printf( " failed (%u)\n", i );
550 printf( " GOT: " );
551 ecp_point_print( &TMP );
552 printf( " EXPECTED: " );
553 ecp_point_print( &mul_tbl[i] );
554 }
555
556 return( 1 );
557 }
558 }
559
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100560 if( verbose != 0 )
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100561 printf( "passed\n" );
562
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100563 if( verbose != 0 )
564 printf( " ECP test #3 (use_known_dp): " );
565
566 for( i = 0; i <= POLARSSL_ECP_DP_SECP521R1; i++ )
567 {
568 MPI_CHK( ecp_use_known_dp( &grp, i ) );
569 }
570
571 if( verbose != 0 )
572 printf( "passed\n" );
573
574
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100575cleanup:
576
577 if( ret != 0 && verbose != 0 )
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100578 {
579#if defined(POLARSSL_ERROR_C)
580 char error_buf[200];
581 error_strerror( ret, error_buf, 200 );
582 printf( "Unexpected error: %d - %s\n\n", ret, error_buf );
583#else
584 printf( "Unexpected error: %08X\n", ret );
585#endif
586 }
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100587
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +0100588 ecp_group_free( &grp ); ecp_point_free( &O ); ecp_point_free( &TMP );
589
590 ecp_point_free( &A ); ecp_point_free( &B ); ecp_point_free( &C );
591 ecp_point_free( &D ); ecp_point_free( &E ); ecp_point_free( &F );
592 ecp_point_free( &G ); ecp_point_free( &H );
593
594 mpi_free( &m );
595
596 for( i = 0; i <= TEST_GROUP_ORDER; i++ )
597 ecp_point_free( &mul_tbl[i] );
Manuel Pégourié-Gonnardd0dc6312012-11-05 16:28:33 +0100598
599 if( verbose != 0 )
600 printf( "\n" );
601
602 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100603}
604
605#endif
606
607#endif