blob: d53d306a550eb362950126974bdbe9e0b4d318d1 [file] [log] [blame]
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001/*
2 * Elliptic curves over GF(p)
3 *
Paul Bakkercf4365f2013-01-16 17:00:43 +01004 * Copyright (C) 2006-2013, Brainspark B.V.
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01005 *
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é-Gonnardd070f512012-11-08 17:40:51 +010030 * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +010031 * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +010032 * RFC 4492 for the related TLS structures and constants
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020033 *
34 * [1] OKEYA, Katsuyuki and TAKAGI, Tsuyoshi. The width-w NAF method provides
35 * small memory and fast elliptic scalar multiplications secure against
36 * side channel attacks. In : Topics in Cryptology—CT-RSA 2003. Springer
37 * Berlin Heidelberg, 2003. p. 328-343.
38 * <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
39 *
40 * [2] CORON, Jean-Sébastien. Resistance against differential power analysis
41 * for elliptic curve cryptosystems. In : Cryptographic Hardware and
42 * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
43 * <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010044 */
45
46#include "polarssl/config.h"
47
48#if defined(POLARSSL_ECP_C)
49
50#include "polarssl/ecp.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020051
52#if defined(POLARSSL_MEMORY_C)
53#include "polarssl/memory.h"
54#else
55#define polarssl_malloc malloc
56#define polarssl_free free
57#endif
58
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +010059#include <limits.h>
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +010060#include <stdlib.h>
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +010061
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010062#if defined(POLARSSL_SELF_TEST)
63/*
64 * Counts of point addition and doubling operations.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +020065 * Used to test resistance of point multiplication to simple timing attacks.
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +010066 */
67unsigned long add_count, dbl_count;
68#endif
69
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +010070/*
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020071 * List of supported curves:
72 * - internal ID
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020073 * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2)
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020074 * - size in bits
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020075 * - readable name
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020076 */
Manuel Pégourié-Gonnarda79d1232013-09-17 15:42:35 +020077const ecp_curve_info ecp_supported_curves[] =
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020078{
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020079#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
80 { POLARSSL_ECP_DP_BP512R1, 28, 512, "brainpool512r1" },
81#endif
82#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
83 { POLARSSL_ECP_DP_BP384R1, 27, 384, "brainpool384r1" },
84#endif
85#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
86 { POLARSSL_ECP_DP_BP256R1, 26, 256, "brainpool256r1" },
87#endif
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020088#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020089 { POLARSSL_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020090#endif
91#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020092 { POLARSSL_ECP_DP_SECP384R1, 24, 384, "secp384r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020093#endif
94#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020095 { POLARSSL_ECP_DP_SECP256R1, 23, 256, "secp256r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020096#endif
97#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +020098 { POLARSSL_ECP_DP_SECP224R1, 21, 224, "secp224r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +020099#endif
100#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200101 { POLARSSL_ECP_DP_SECP192R1, 19, 192, "secp192r1" },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200102#endif
Manuel Pégourié-Gonnard8195c1a2013-10-07 19:40:41 +0200103 { POLARSSL_ECP_DP_NONE, 0, 0, NULL },
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200104};
105
106/*
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200107 * List of supported curves and associated info
108 */
109const ecp_curve_info *ecp_curve_list( void )
110{
111 return ecp_supported_curves;
112}
113
114/*
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100115 * Initialize (the components of) a point
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100116 */
117void ecp_point_init( ecp_point *pt )
118{
119 if( pt == NULL )
120 return;
121
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100122 mpi_init( &pt->X );
123 mpi_init( &pt->Y );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100124 mpi_init( &pt->Z );
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +0100125}
126
127/*
128 * Initialize (the components of) a group
129 */
130void ecp_group_init( ecp_group *grp )
131{
132 if( grp == NULL )
133 return;
134
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200135 memset( grp, 0, sizeof( ecp_group ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100136}
137
138/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200139 * Initialize (the components of) a key pair
140 */
141void ecp_keypair_init( ecp_keypair *key )
142{
143 if ( key == NULL )
144 return;
145
146 ecp_group_init( &key->grp );
147 mpi_init( &key->d );
148 ecp_point_init( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200149}
150
151/*
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100152 * Unallocate (the components of) a point
153 */
154void ecp_point_free( ecp_point *pt )
155{
156 if( pt == NULL )
157 return;
158
159 mpi_free( &( pt->X ) );
160 mpi_free( &( pt->Y ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100161 mpi_free( &( pt->Z ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100162}
163
164/*
165 * Unallocate (the components of) a group
166 */
167void ecp_group_free( ecp_group *grp )
168{
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200169 size_t i;
170
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100171 if( grp == NULL )
172 return;
173
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100174 mpi_free( &grp->P );
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200175 mpi_free( &grp->A );
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100176 mpi_free( &grp->B );
177 ecp_point_free( &grp->G );
178 mpi_free( &grp->N );
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200179
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +0200180 if( grp->T != NULL )
181 {
182 for( i = 0; i < grp->T_size; i++ )
183 ecp_point_free( &grp->T[i] );
184 polarssl_free( grp->T );
185 }
186
Manuel Pégourié-Gonnardc9727702013-09-16 18:56:28 +0200187 memset( grp, 0, sizeof( ecp_group ) );
Manuel Pégourié-Gonnard1e8c8ec2012-10-31 19:24:21 +0100188}
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +0100189
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100190/*
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200191 * Unallocate (the components of) a key pair
192 */
193void ecp_keypair_free( ecp_keypair *key )
194{
195 if ( key == NULL )
196 return;
197
198 ecp_group_free( &key->grp );
199 mpi_free( &key->d );
200 ecp_point_free( &key->Q );
Manuel Pégourié-Gonnardb8c6e0e2013-07-01 13:40:52 +0200201}
202
203/*
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100204 * Set point to zero
205 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100206int ecp_set_zero( ecp_point *pt )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100207{
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100208 int ret;
209
210 MPI_CHK( mpi_lset( &pt->X , 1 ) );
211 MPI_CHK( mpi_lset( &pt->Y , 1 ) );
212 MPI_CHK( mpi_lset( &pt->Z , 0 ) );
213
214cleanup:
215 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100216}
217
218/*
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100219 * Tell if a point is zero
220 */
221int ecp_is_zero( ecp_point *pt )
222{
223 return( mpi_cmp_int( &pt->Z, 0 ) == 0 );
224}
225
226/*
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100227 * Copy the contents of Q into P
228 */
229int ecp_copy( ecp_point *P, const ecp_point *Q )
230{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100231 int ret;
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100232
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100233 MPI_CHK( mpi_copy( &P->X, &Q->X ) );
234 MPI_CHK( mpi_copy( &P->Y, &Q->Y ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100235 MPI_CHK( mpi_copy( &P->Z, &Q->Z ) );
Manuel Pégourié-Gonnard883f3132012-11-02 09:40:25 +0100236
237cleanup:
238 return( ret );
239}
Manuel Pégourié-Gonnard5179e462012-10-31 19:37:54 +0100240
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +0100241/*
Manuel Pégourié-Gonnarde09631b2013-08-12 15:44:31 +0200242 * Copy the contents of a group object
243 */
244int ecp_group_copy( ecp_group *dst, const ecp_group *src )
245{
246 return ecp_use_known_dp( dst, src->id );
247}
248
249/*
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100250 * Import a non-zero point from ASCII strings
251 */
252int ecp_point_read_string( ecp_point *P, int radix,
253 const char *x, const char *y )
254{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100255 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100256
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100257 MPI_CHK( mpi_read_string( &P->X, radix, x ) );
258 MPI_CHK( mpi_read_string( &P->Y, radix, y ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100259 MPI_CHK( mpi_lset( &P->Z, 1 ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100260
261cleanup:
262 return( ret );
263}
264
265/*
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200266 * Import an ECP group from ASCII strings, general case (A used)
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100267 */
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200268static int ecp_group_read_string_gen( ecp_group *grp, int radix,
269 const char *p, const char *a, const char *b,
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100270 const char *gx, const char *gy, const char *n)
271{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100272 int ret;
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100273
274 MPI_CHK( mpi_read_string( &grp->P, radix, p ) );
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200275 MPI_CHK( mpi_read_string( &grp->A, radix, a ) );
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100276 MPI_CHK( mpi_read_string( &grp->B, radix, b ) );
277 MPI_CHK( ecp_point_read_string( &grp->G, radix, gx, gy ) );
278 MPI_CHK( mpi_read_string( &grp->N, radix, n ) );
279
Manuel Pégourié-Gonnard773ed542012-11-18 13:19:07 +0100280 grp->pbits = mpi_msb( &grp->P );
281 grp->nbits = mpi_msb( &grp->N );
282
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100283cleanup:
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200284 if( ret != 0 )
285 ecp_group_free( grp );
286
287 return( ret );
288}
289
290/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +0200291 * Import an ECP group from ASCII strings, case A == -3
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200292 */
293int ecp_group_read_string( ecp_group *grp, int radix,
294 const char *p, const char *b,
295 const char *gx, const char *gy, const char *n)
296{
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +0200297 int ret;
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200298
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +0200299 MPI_CHK( ecp_group_read_string_gen( grp, radix, p, "00", b, gx, gy, n ) );
300 MPI_CHK( mpi_add_int( &grp->A, &grp->P, -3 ) );
301
302cleanup:
303 if( ret != 0 )
304 ecp_group_free( grp );
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200305
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100306 return( ret );
307}
308
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100309/*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100310 * Export a point into unsigned binary data (SEC1 2.3.3)
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100311 */
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100312int ecp_point_write_binary( const ecp_group *grp, const ecp_point *P,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100313 int format, size_t *olen,
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100314 unsigned char *buf, size_t buflen )
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100315{
Paul Bakkera280d0f2013-04-08 13:40:17 +0200316 int ret = 0;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100317 size_t plen;
318
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100319 if( format != POLARSSL_ECP_PF_UNCOMPRESSED &&
320 format != POLARSSL_ECP_PF_COMPRESSED )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100321 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100322
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100323 /*
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100324 * Common case: P == 0
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100325 */
326 if( mpi_cmp_int( &P->Z, 0 ) == 0 )
327 {
328 if( buflen < 1 )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100329 return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100330
331 buf[0] = 0x00;
332 *olen = 1;
333
334 return( 0 );
335 }
336
337 plen = mpi_size( &grp->P );
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100338
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100339 if( format == POLARSSL_ECP_PF_UNCOMPRESSED )
340 {
341 *olen = 2 * plen + 1;
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100342
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100343 if( buflen < *olen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100344 return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100345
346 buf[0] = 0x04;
347 MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) );
348 MPI_CHK( mpi_write_binary( &P->Y, buf + 1 + plen, plen ) );
349 }
350 else if( format == POLARSSL_ECP_PF_COMPRESSED )
351 {
352 *olen = plen + 1;
353
354 if( buflen < *olen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100355 return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
Manuel Pégourié-Gonnard37d218a2012-11-24 15:19:55 +0100356
357 buf[0] = 0x02 + mpi_get_bit( &P->Y, 0 );
358 MPI_CHK( mpi_write_binary( &P->X, buf + 1, plen ) );
359 }
Manuel Pégourié-Gonnarde19feb52012-11-24 14:10:14 +0100360
361cleanup:
362 return( ret );
363}
364
365/*
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100366 * Import a point from unsigned binary data (SEC1 2.3.4)
367 */
Manuel Pégourié-Gonnard7e860252013-02-10 10:58:48 +0100368int ecp_point_read_binary( const ecp_group *grp, ecp_point *pt,
369 const unsigned char *buf, size_t ilen ) {
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100370 int ret;
371 size_t plen;
372
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100373 if( ilen == 1 && buf[0] == 0x00 )
Manuel Pégourié-Gonnardd84895d2013-02-10 10:53:04 +0100374 return( ecp_set_zero( pt ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100375
Manuel Pégourié-Gonnardd84895d2013-02-10 10:53:04 +0100376 plen = mpi_size( &grp->P );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100377
378 if( ilen != 2 * plen + 1 || buf[0] != 0x04 )
Manuel Pégourié-Gonnardd84895d2013-02-10 10:53:04 +0100379 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100380
Manuel Pégourié-Gonnardd84895d2013-02-10 10:53:04 +0100381 MPI_CHK( mpi_read_binary( &pt->X, buf + 1, plen ) );
382 MPI_CHK( mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
383 MPI_CHK( mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnard5e402d82012-11-24 16:19:42 +0100384
385cleanup:
386 return( ret );
387}
388
389/*
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100390 * Import a point from a TLS ECPoint record (RFC 4492)
391 * struct {
392 * opaque point <1..2^8-1>;
393 * } ECPoint;
394 */
395int ecp_tls_read_point( const ecp_group *grp, ecp_point *pt,
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100396 const unsigned char **buf, size_t buf_len )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100397{
398 unsigned char data_len;
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100399 const unsigned char *buf_start;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100400
401 /*
402 * We must have at least two bytes (1 for length, at least of for data)
403 */
404 if( buf_len < 2 )
405 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
406
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100407 data_len = *(*buf)++;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100408 if( data_len < 1 || data_len > buf_len - 1 )
409 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
410
Manuel Pégourié-Gonnard98f51812013-02-10 13:38:29 +0100411 /*
412 * Save buffer start for read_binary and update buf
413 */
414 buf_start = *buf;
415 *buf += data_len;
416
417 return ecp_point_read_binary( grp, pt, buf_start, data_len );
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100418}
419
420/*
421 * Export a point as a TLS ECPoint record (RFC 4492)
422 * struct {
423 * opaque point <1..2^8-1>;
424 * } ECPoint;
425 */
426int ecp_tls_write_point( const ecp_group *grp, const ecp_point *pt,
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100427 int format, size_t *olen,
428 unsigned char *buf, size_t blen )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100429{
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100430 int ret;
431
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100432 /*
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100433 * buffer length must be at least one, for our length byte
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100434 */
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100435 if( blen < 1 )
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100436 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
437
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100438 if( ( ret = ecp_point_write_binary( grp, pt, format,
439 olen, buf + 1, blen - 1) ) != 0 )
440 return( ret );
441
442 /*
443 * write length to the first byte and update total length
444 */
Paul Bakkerb9cfaa02013-10-11 18:58:55 +0200445 buf[0] = (unsigned char) *olen;
Manuel Pégourié-Gonnard420f1eb2013-02-10 12:22:46 +0100446 ++*olen;
447
448 return 0;
Manuel Pégourié-Gonnard00794052013-02-09 19:00:07 +0100449}
450
451/*
Manuel Pégourié-Gonnard773ed542012-11-18 13:19:07 +0100452 * Wrapper around fast quasi-modp functions, with fall-back to mpi_mod_mpi.
453 * See the documentation of struct ecp_group.
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100454 */
455static int ecp_modp( mpi *N, const ecp_group *grp )
456{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100457 int ret;
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100458
459 if( grp->modp == NULL )
460 return( mpi_mod_mpi( N, N, &grp->P ) );
461
462 if( mpi_cmp_int( N, 0 ) < 0 || mpi_msb( N ) > 2 * grp->pbits )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +0200463 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100464
465 MPI_CHK( grp->modp( N ) );
466
467 while( mpi_cmp_int( N, 0 ) < 0 )
468 MPI_CHK( mpi_add_mpi( N, N, &grp->P ) );
469
470 while( mpi_cmp_mpi( N, &grp->P ) >= 0 )
471 MPI_CHK( mpi_sub_mpi( N, N, &grp->P ) );
472
473cleanup:
474 return( ret );
475}
476
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200477#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100478
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200479/* Add 64-bit chunks (dst += src) and update carry */
480static inline void add_64( t_uint *dst, t_uint *src, t_uint *carry )
481{
482 unsigned char i;
483 t_uint c = 0;
484 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++, src++ )
485 {
486 *dst += c; c = ( *dst < c );
487 *dst += *src; c += ( *dst < *src );
488 }
489 *carry += c;
490}
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100491
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200492/* Add carry to a 64-bit chunk and update carry */
493static inline void carry64( t_uint *dst, t_uint *carry )
494{
495 unsigned char i;
496 for( i = 0; i < 8 / sizeof( t_uint ); i++, dst++ )
497 {
498 *dst += *carry;
499 *carry = ( *dst < *carry );
500 }
501}
502
503#define OFFSET ( 8 / sizeof( t_uint ) )
504#define A( i ) ( N->p + ( i ) * OFFSET )
505#define ADD( i ) add_64( p, A( i ), &c )
506#define NEXT p += OFFSET; carry64( p, &c )
507#define LAST p += OFFSET; *p = c; while( ++p < end ) *p = 0
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100508
509/*
510 * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
511 */
512static int ecp_mod_p192( mpi *N )
513{
514 int ret;
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200515 t_uint c = 0;
516 t_uint *p, *end;
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100517
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200518 /* Make sure we have the correct number of blocks */
519 MPI_CHK( mpi_grow( N, 6 * OFFSET ) );
520 p = N->p;
521 end = p + N->n;
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100522
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200523 ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5
524 ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5
525 ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100526
527cleanup:
528 return( ret );
529}
Manuel Pégourié-Gonnardd1e7a452013-10-22 21:03:16 +0200530
531#undef OFFSET
532#undef A
533#undef ADD
534#undef NEXT
535#undef LAST
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200536#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100537
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200538#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100539/*
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100540 * Size of p521 in terms of t_uint
541 */
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100542#define P521_SIZE_INT ( 521 / CHAR_BIT / sizeof( t_uint ) + 1 )
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100543
544/*
545 * Bits to keep in the most significant t_uint
546 */
547#if defined(POLARSS_HAVE_INT8)
548#define P521_MASK 0x01
549#else
550#define P521_MASK 0x01FF
551#endif
552
553/*
554 * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100555 */
556static int ecp_mod_p521( mpi *N )
557{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100558 int ret;
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100559 t_uint Mp[P521_SIZE_INT];
560 mpi M;
561
562 if( N->n < P521_SIZE_INT )
563 return( 0 );
564
565 memset( Mp, 0, P521_SIZE_INT * sizeof( t_uint ) );
566 memcpy( Mp, N->p, P521_SIZE_INT * sizeof( t_uint ) );
567 Mp[P521_SIZE_INT - 1] &= P521_MASK;
568
569 M.s = 1;
570 M.n = P521_SIZE_INT;
571 M.p = Mp;
572
573 MPI_CHK( mpi_shift_r( N, 521 ) );
574
575 MPI_CHK( mpi_add_abs( N, N, &M ) );
576
577cleanup:
578 return( ret );
579}
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200580#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100581
582/*
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100583 * Domain parameters for secp192r1
584 */
585#define SECP192R1_P \
586 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"
587#define SECP192R1_B \
588 "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"
589#define SECP192R1_GX \
590 "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
591#define SECP192R1_GY \
592 "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"
593#define SECP192R1_N \
594 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"
595
596/*
597 * Domain parameters for secp224r1
598 */
599#define SECP224R1_P \
600 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"
601#define SECP224R1_B \
602 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"
603#define SECP224R1_GX \
604 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
605#define SECP224R1_GY \
606 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"
607#define SECP224R1_N \
608 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"
609
610/*
611 * Domain parameters for secp256r1
612 */
613#define SECP256R1_P \
614 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"
615#define SECP256R1_B \
616 "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"
617#define SECP256R1_GX \
618 "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
619#define SECP256R1_GY \
620 "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"
621#define SECP256R1_N \
622 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"
623
624/*
625 * Domain parameters for secp384r1
626 */
627#define SECP384R1_P \
628 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
629 "FFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"
630#define SECP384R1_B \
631 "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE814112" \
632 "0314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF"
633#define SECP384R1_GX \
634 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B98" \
635 "59F741E082542A385502F25DBF55296C3A545E3872760AB7"
636#define SECP384R1_GY \
637 "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147C" \
638 "E9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"
639#define SECP384R1_N \
640 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
641 "C7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"
642
643/*
644 * Domain parameters for secp521r1
645 */
646#define SECP521R1_P \
647 "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
648 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
649 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
650#define SECP521R1_B \
651 "00000051953EB9618E1C9A1F929A21A0B68540EEA2DA725B" \
652 "99B315F3B8B489918EF109E156193951EC7E937B1652C0BD" \
653 "3BB1BF073573DF883D2C34F1EF451FD46B503F00"
654#define SECP521R1_GX \
655 "000000C6858E06B70404E9CD9E3ECB662395B4429C648139" \
656 "053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127" \
657 "A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
658#define SECP521R1_GY \
659 "0000011839296A789A3BC0045C8A5FB42C7D1BD998F54449" \
660 "579B446817AFBD17273E662C97EE72995EF42640C550B901" \
661 "3FAD0761353C7086A272C24088BE94769FD16650"
662#define SECP521R1_N \
663 "000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \
664 "FFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148" \
665 "F709A5D03BB5C9B8899C47AEBB6FB71E91386409"
666
667/*
Manuel Pégourié-Gonnardcec4a532013-10-07 19:52:27 +0200668 * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
669 */
670#define BP256R1_P \
671 "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377"
672#define BP256R1_A \
673 "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9"
674#define BP256R1_B \
675 "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6"
676#define BP256R1_GX \
677 "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262"
678#define BP256R1_GY \
679 "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997"
680#define BP256R1_N \
681 "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"
682
683/*
684 * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
685 */
686#define BP384R1_P \
687 "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB711" \
688 "23ACD3A729901D1A71874700133107EC53"
689#define BP384R1_A \
690 "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F9" \
691 "0F8AA5814A503AD4EB04A8C7DD22CE2826"
692#define BP384R1_B \
693 "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62" \
694 "D57CB4390295DBC9943AB78696FA504C11"
695#define BP384R1_GX \
696 "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10" \
697 "E8E826E03436D646AAEF87B2E247D4AF1E"
698#define BP384R1_GY \
699 "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129" \
700 "280E4646217791811142820341263C5315"
701#define BP384R1_N \
702 "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425" \
703 "A7CF3AB6AF6B7FC3103B883202E9046565"
704
705/*
706 * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
707 */
708#define BP512R1_P \
709 "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \
710 "717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3"
711#define BP512R1_A \
712 "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863" \
713 "BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA"
714#define BP512R1_B \
715 "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117" \
716 "A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723"
717#define BP512R1_GX \
718 "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D009" \
719 "8EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822"
720#define BP512R1_GY \
721 "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F81" \
722 "11B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892"
723#define BP512R1_N \
724 "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308" \
725 "70553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069"
726
727/*
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100728 * Set a group using well-known domain parameters
729 */
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100730int ecp_use_known_dp( ecp_group *grp, ecp_group_id id )
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100731{
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100732 grp->id = id;
733
734 switch( id )
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100735 {
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200736#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100737 case POLARSSL_ECP_DP_SECP192R1:
Manuel Pégourié-Gonnard84338242012-11-11 20:45:18 +0100738 grp->modp = ecp_mod_p192;
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100739 return( ecp_group_read_string( grp, 16,
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100740 SECP192R1_P, SECP192R1_B,
741 SECP192R1_GX, SECP192R1_GY, SECP192R1_N ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200742#endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100743
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200744#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100745 case POLARSSL_ECP_DP_SECP224R1:
746 return( ecp_group_read_string( grp, 16,
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100747 SECP224R1_P, SECP224R1_B,
748 SECP224R1_GX, SECP224R1_GY, SECP224R1_N ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200749#endif /* POLARSSL_ECP_DP_SECP224R1_ENABLED */
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100750
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200751#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100752 case POLARSSL_ECP_DP_SECP256R1:
753 return( ecp_group_read_string( grp, 16,
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100754 SECP256R1_P, SECP256R1_B,
755 SECP256R1_GX, SECP256R1_GY, SECP256R1_N ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200756#endif /* POLARSSL_ECP_DP_SECP256R1_ENABLED */
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100757
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200758#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100759 case POLARSSL_ECP_DP_SECP384R1:
760 return( ecp_group_read_string( grp, 16,
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100761 SECP384R1_P, SECP384R1_B,
762 SECP384R1_GX, SECP384R1_GY, SECP384R1_N ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200763#endif /* POLARSSL_ECP_DP_SECP384R1_ENABLED */
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100764
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200765#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100766 case POLARSSL_ECP_DP_SECP521R1:
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100767 grp->modp = ecp_mod_p521;
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100768 return( ecp_group_read_string( grp, 16,
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100769 SECP521R1_P, SECP521R1_B,
770 SECP521R1_GX, SECP521R1_GY, SECP521R1_N ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +0200771#endif /* POLARSSL_ECP_DP_SECP521R1_ENABLED */
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100772
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200773#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
774 case POLARSSL_ECP_DP_BP256R1:
775 return( ecp_group_read_string_gen( grp, 16,
776 BP256R1_P, BP256R1_A, BP256R1_B,
777 BP256R1_GX, BP256R1_GY, BP256R1_N ) );
778#endif /* POLARSSL_ECP_DP_BP256R1_ENABLED */
779
780#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
781 case POLARSSL_ECP_DP_BP384R1:
782 return( ecp_group_read_string_gen( grp, 16,
783 BP384R1_P, BP384R1_A, BP384R1_B,
784 BP384R1_GX, BP384R1_GY, BP384R1_N ) );
785#endif /* POLARSSL_ECP_DP_BP384R1_ENABLED */
786
787#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
788 case POLARSSL_ECP_DP_BP512R1:
789 return( ecp_group_read_string_gen( grp, 16,
790 BP512R1_P, BP512R1_A, BP512R1_B,
791 BP512R1_GX, BP512R1_GY, BP512R1_N ) );
792#endif /* POLARSSL_ECP_DP_BP512R1_ENABLED */
793
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200794 default:
Manuel Pégourié-Gonnarda070ada2013-10-08 12:04:56 +0200795 ecp_group_free( grp );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200796 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
797 }
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100798}
799
800/*
801 * Set a group from an ECParameters record (RFC 4492)
802 */
Manuel Pégourié-Gonnard7c145c62013-02-10 13:20:52 +0100803int ecp_tls_read_group( ecp_group *grp, const unsigned char **buf, size_t len )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100804{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200805 uint16_t tls_id;
806 const ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100807
808 /*
809 * We expect at least three bytes (see below)
810 */
811 if( len < 3 )
812 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
813
814 /*
815 * First byte is curve_type; only named_curve is handled
816 */
Manuel Pégourié-Gonnard7c145c62013-02-10 13:20:52 +0100817 if( *(*buf)++ != POLARSSL_ECP_TLS_NAMED_CURVE )
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100818 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
819
820 /*
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100821 * Next two bytes are the namedcurve value
Manuel Pégourié-Gonnard1a967282013-02-09 17:03:58 +0100822 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200823 tls_id = *(*buf)++;
824 tls_id <<= 8;
825 tls_id |= *(*buf)++;
826
827 if( ( curve_info = ecp_curve_info_from_tls_id( tls_id ) ) == NULL )
828 return( POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE );
829
830 return ecp_use_known_dp( grp, curve_info->grp_id );
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100831}
832
833/*
834 * Write the ECParameters record corresponding to a group (RFC 4492)
835 */
836int ecp_tls_write_group( const ecp_group *grp, size_t *olen,
837 unsigned char *buf, size_t blen )
838{
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200839 const ecp_curve_info *curve_info;
840
841 if( ( curve_info = ecp_curve_info_from_grp_id( grp->id ) ) == NULL )
842 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200843
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100844 /*
845 * We are going to write 3 bytes (see below)
846 */
847 *olen = 3;
848 if( blen < *olen )
849 return( POLARSSL_ERR_ECP_BUFFER_TOO_SMALL );
850
851 /*
852 * First byte is curve_type, always named_curve
853 */
854 *buf++ = POLARSSL_ECP_TLS_NAMED_CURVE;
855
856 /*
857 * Next two bytes are the namedcurve value
858 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200859 buf[0] = curve_info->tls_id >> 8;
860 buf[1] = curve_info->tls_id & 0xFF;
Manuel Pégourié-Gonnardb3258872013-02-10 12:06:19 +0100861
862 return 0;
Manuel Pégourié-Gonnarda5402fe2012-11-07 20:24:05 +0100863}
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +0100864
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200865/*
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200866 * Get the curve info from the TLS identifier
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200867 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200868const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200869{
Manuel Pégourié-Gonnarda79d1232013-09-17 15:42:35 +0200870 const ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200871
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200872 for( curve_info = ecp_curve_list();
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200873 curve_info->grp_id != POLARSSL_ECP_DP_NONE;
874 curve_info++ )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200875 {
Manuel Pégourié-Gonnard56cd3192013-09-17 17:23:07 +0200876 if( curve_info->tls_id == tls_id )
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200877 return( curve_info );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200878 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200879
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200880 return( NULL );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200881}
882
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200883/*
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200884 * Get the curve info for the internal identifer
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200885 */
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200886const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200887{
Manuel Pégourié-Gonnarda79d1232013-09-17 15:42:35 +0200888 const ecp_curve_info *curve_info;
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200889
Manuel Pégourié-Gonnardda179e42013-09-18 15:31:24 +0200890 for( curve_info = ecp_curve_list();
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200891 curve_info->grp_id != POLARSSL_ECP_DP_NONE;
892 curve_info++ )
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200893 {
Manuel Pégourié-Gonnard56cd3192013-09-17 17:23:07 +0200894 if( curve_info->grp_id == grp_id )
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200895 return( curve_info );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200896 }
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200897
Manuel Pégourié-Gonnardf24b4a72013-09-23 18:14:50 +0200898 return( NULL );
Manuel Pégourié-Gonnard70380392013-09-16 16:19:53 +0200899}
Manuel Pégourié-Gonnard568c9cf2013-09-16 17:30:04 +0200900
Manuel Pégourié-Gonnard847395a2012-11-05 13:13:44 +0100901/*
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100902 * Fast mod-p functions expect their argument to be in the 0..p^2 range.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100903 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100904 * In order to guarantee that, we need to ensure that operands of
905 * mpi_mul_mpi are in the 0..p range. So, after each operation we will
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100906 * bring the result back to this range.
907 *
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100908 * The following macros are shortcuts for doing that.
Manuel Pégourié-Gonnarddada4da2012-11-10 14:23:17 +0100909 */
910
911/*
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100912 * Reduce a mpi mod p in-place, general case, to use after mpi_mul_mpi
913 */
Manuel Pégourié-Gonnard62aad142012-11-10 00:27:12 +0100914#define MOD_MUL( N ) MPI_CHK( ecp_modp( &N, grp ) )
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +0100915
916/*
917 * Reduce a mpi mod p in-place, to use after mpi_sub_mpi
918 */
919#define MOD_SUB( N ) \
920 while( mpi_cmp_int( &N, 0 ) < 0 ) \
921 MPI_CHK( mpi_add_mpi( &N, &N, &grp->P ) )
922
923/*
924 * Reduce a mpi mod p in-place, to use after mpi_add_mpi and mpi_mul_int
925 */
926#define MOD_ADD( N ) \
927 while( mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \
928 MPI_CHK( mpi_sub_mpi( &N, &N, &grp->P ) )
929
930/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100931 * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1)
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100932 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100933static int ecp_normalize( const ecp_group *grp, ecp_point *pt )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100934{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +0100935 int ret;
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100936 mpi Zi, ZZi;
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100937
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100938 if( mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100939 return( 0 );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100940
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100941 mpi_init( &Zi ); mpi_init( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100942
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100943 /*
944 * X = X / Z^2 mod p
945 */
946 MPI_CHK( mpi_inv_mod( &Zi, &pt->Z, &grp->P ) );
947 MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
948 MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100949
950 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100951 * Y = Y / Z^3 mod p
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100952 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100953 MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y );
954 MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100955
956 /*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100957 * Z = 1
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100958 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +0100959 MPI_CHK( mpi_lset( &pt->Z, 1 ) );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100960
961cleanup:
962
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100963 mpi_free( &Zi ); mpi_free( &ZZi );
Manuel Pégourié-Gonnardd070f512012-11-08 17:40:51 +0100964
965 return( ret );
966}
967
968/*
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100969 * Normalize jacobian coordinates of an array of points,
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +0100970 * using Montgomery's trick to perform only one inversion mod P.
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100971 * (See for example Cohen's "A Course in Computational Algebraic Number
972 * Theory", Algorithm 10.3.4.)
973 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +0200974 * Warning: fails (returning an error) if one of the points is zero!
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +0100975 * This should never happen, see choice of w in ecp_mul().
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100976 */
977static int ecp_normalize_many( const ecp_group *grp,
978 ecp_point T[], size_t t_len )
979{
980 int ret;
981 size_t i;
982 mpi *c, u, Zi, ZZi;
983
984 if( t_len < 2 )
985 return( ecp_normalize( grp, T ) );
986
Paul Bakker6e339b52013-07-03 13:37:05 +0200987 if( ( c = (mpi *) polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +0200988 return( POLARSSL_ERR_ECP_MALLOC_FAILED );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +0100989
990 mpi_init( &u ); mpi_init( &Zi ); mpi_init( &ZZi );
991 for( i = 0; i < t_len; i++ )
992 mpi_init( &c[i] );
993
994 /*
995 * c[i] = Z_0 * ... * Z_i
996 */
997 MPI_CHK( mpi_copy( &c[0], &T[0].Z ) );
998 for( i = 1; i < t_len; i++ )
999 {
1000 MPI_CHK( mpi_mul_mpi( &c[i], &c[i-1], &T[i].Z ) );
1001 MOD_MUL( c[i] );
1002 }
1003
1004 /*
1005 * u = 1 / (Z_0 * ... * Z_n) mod P
1006 */
1007 MPI_CHK( mpi_inv_mod( &u, &c[t_len-1], &grp->P ) );
1008
1009 for( i = t_len - 1; ; i-- )
1010 {
1011 /*
1012 * Zi = 1 / Z_i mod p
1013 * u = 1 / (Z_0 * ... * Z_i) mod P
1014 */
1015 if( i == 0 ) {
1016 MPI_CHK( mpi_copy( &Zi, &u ) );
1017 }
1018 else
1019 {
1020 MPI_CHK( mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi );
1021 MPI_CHK( mpi_mul_mpi( &u, &u, &T[i].Z ) ); MOD_MUL( u );
1022 }
1023
1024 /*
1025 * proceed as in normalize()
1026 */
1027 MPI_CHK( mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi );
1028 MPI_CHK( mpi_mul_mpi( &T[i].X, &T[i].X, &ZZi ) ); MOD_MUL( T[i].X );
1029 MPI_CHK( mpi_mul_mpi( &T[i].Y, &T[i].Y, &ZZi ) ); MOD_MUL( T[i].Y );
1030 MPI_CHK( mpi_mul_mpi( &T[i].Y, &T[i].Y, &Zi ) ); MOD_MUL( T[i].Y );
1031 MPI_CHK( mpi_lset( &T[i].Z, 1 ) );
1032
1033 if( i == 0 )
1034 break;
1035 }
1036
1037cleanup:
1038
1039 mpi_free( &u ); mpi_free( &Zi ); mpi_free( &ZZi );
1040 for( i = 0; i < t_len; i++ )
1041 mpi_free( &c[i] );
Paul Bakker6e339b52013-07-03 13:37:05 +02001042 polarssl_free( c );
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001043
1044 return( ret );
1045}
1046
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001047/*
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001048 * Point doubling R = 2 P, Jacobian coordinates
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001049 *
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001050 * http://www.hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian/doubling/dbl-2007-bl.op3
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001051 * with heavy variable renaming, some reordering and one minor modification
1052 * (a = 2 * b, c = d - 2a replaced with c = d, c = c - b, c = c - b)
1053 * in order to use a lot less intermediate variables (6 vs 25).
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001054 */
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001055static int ecp_double_jac( const ecp_group *grp, ecp_point *R,
1056 const ecp_point *P )
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001057{
1058 int ret;
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001059 mpi T1, T2, T3, X3, Y3, Z3;
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001060
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001061#if defined(POLARSSL_SELF_TEST)
1062 dbl_count++;
1063#endif
1064
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001065 mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 );
1066 mpi_init( &X3 ); mpi_init( &Y3 ); mpi_init( &Z3 );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001067
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001068 MPI_CHK( mpi_mul_mpi( &T3, &P->X, &P->X ) ); MOD_MUL( T3 );
1069 MPI_CHK( mpi_mul_mpi( &T2, &P->Y, &P->Y ) ); MOD_MUL( T2 );
1070 MPI_CHK( mpi_mul_mpi( &Y3, &T2, &T2 ) ); MOD_MUL( Y3 );
1071 MPI_CHK( mpi_add_mpi( &X3, &P->X, &T2 ) ); MOD_ADD( X3 );
1072 MPI_CHK( mpi_mul_mpi( &X3, &X3, &X3 ) ); MOD_MUL( X3 );
1073 MPI_CHK( mpi_sub_mpi( &X3, &X3, &Y3 ) ); MOD_SUB( X3 );
1074 MPI_CHK( mpi_sub_mpi( &X3, &X3, &T3 ) ); MOD_SUB( X3 );
1075 MPI_CHK( mpi_mul_int( &T1, &X3, 2 ) ); MOD_ADD( T1 );
1076 MPI_CHK( mpi_mul_mpi( &Z3, &P->Z, &P->Z ) ); MOD_MUL( Z3 );
1077 MPI_CHK( mpi_mul_mpi( &X3, &Z3, &Z3 ) ); MOD_MUL( X3 );
1078 MPI_CHK( mpi_mul_int( &T3, &T3, 3 ) ); MOD_ADD( T3 );
1079 MPI_CHK( mpi_mul_mpi( &X3, &X3, &grp->A ) ); MOD_MUL( X3 );
1080 MPI_CHK( mpi_add_mpi( &T3, &T3, &X3 ) ); MOD_ADD( T3 );
1081 MPI_CHK( mpi_mul_mpi( &X3, &T3, &T3 ) ); MOD_MUL( X3 );
1082 MPI_CHK( mpi_sub_mpi( &X3, &X3, &T1 ) ); MOD_SUB( X3 );
1083 MPI_CHK( mpi_sub_mpi( &X3, &X3, &T1 ) ); MOD_SUB( X3 );
1084 MPI_CHK( mpi_sub_mpi( &T1, &T1, &X3 ) ); MOD_SUB( T1 );
1085 MPI_CHK( mpi_mul_mpi( &T1, &T3, &T1 ) ); MOD_MUL( T1 );
1086 MPI_CHK( mpi_mul_int( &T3, &Y3, 8 ) ); MOD_ADD( T3 );
1087 MPI_CHK( mpi_sub_mpi( &Y3, &T1, &T3 ) ); MOD_SUB( Y3 );
1088 MPI_CHK( mpi_add_mpi( &T1, &P->Y, &P->Z ) ); MOD_ADD( T1 );
1089 MPI_CHK( mpi_mul_mpi( &T1, &T1, &T1 ) ); MOD_MUL( T1 );
1090 MPI_CHK( mpi_sub_mpi( &T1, &T1, &T2 ) ); MOD_SUB( T1 );
1091 MPI_CHK( mpi_sub_mpi( &Z3, &T1, &Z3 ) ); MOD_SUB( Z3 );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001092
1093 MPI_CHK( mpi_copy( &R->X, &X3 ) );
1094 MPI_CHK( mpi_copy( &R->Y, &Y3 ) );
1095 MPI_CHK( mpi_copy( &R->Z, &Z3 ) );
1096
1097cleanup:
Manuel Pégourié-Gonnard0ace4b32013-10-10 12:44:27 +02001098 mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 );
1099 mpi_free( &X3 ); mpi_free( &Y3 ); mpi_free( &Z3 );
Manuel Pégourié-Gonnard1c4aa242013-10-09 16:09:46 +02001100
1101 return( ret );
1102}
1103
1104/*
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001105 * Addition or subtraction: R = P + Q or R = P + Q,
1106 * mixed affine-Jacobian coordinates (GECC 3.22)
1107 *
1108 * The coordinates of Q must be normalized (= affine),
1109 * but those of P don't need to. R is not normalized.
1110 *
1111 * If sign >= 0, perform addition, otherwise perform subtraction,
1112 * taking advantage of the fact that, for Q != 0, we have
1113 * -Q = (Q.X, -Q.Y, Q.Z)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001114 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001115static int ecp_add_mixed( const ecp_group *grp, ecp_point *R,
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001116 const ecp_point *P, const ecp_point *Q,
1117 signed char sign )
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001118{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001119 int ret;
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001120 mpi T1, T2, T3, T4, X, Y, Z;
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001121
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001122#if defined(POLARSSL_SELF_TEST)
1123 add_count++;
1124#endif
1125
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001126 /*
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001127 * Trivial cases: P == 0 or Q == 0
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001128 * (Check Q first, so that we know Q != 0 when we compute -Q.)
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001129 */
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001130 if( mpi_cmp_int( &Q->Z, 0 ) == 0 )
1131 return( ecp_copy( R, P ) );
1132
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001133 if( mpi_cmp_int( &P->Z, 0 ) == 0 )
1134 {
1135 ret = ecp_copy( R, Q );
1136
1137 /*
1138 * -R.Y mod P = P - R.Y unless R.Y == 0
1139 */
1140 if( ret == 0 && sign < 0)
1141 if( mpi_cmp_int( &R->Y, 0 ) != 0 )
1142 ret = mpi_sub_mpi( &R->Y, &grp->P, &R->Y );
1143
1144 return( ret );
1145 }
1146
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001147 /*
1148 * Make sure Q coordinates are normalized
1149 */
1150 if( mpi_cmp_int( &Q->Z, 1 ) != 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001151 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001152
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001153 mpi_init( &T1 ); mpi_init( &T2 ); mpi_init( &T3 ); mpi_init( &T4 );
1154 mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z );
Manuel Pégourié-Gonnardab38b702012-11-05 17:34:55 +01001155
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001156 MPI_CHK( mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 );
1157 MPI_CHK( mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 );
1158 MPI_CHK( mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 );
1159 MPI_CHK( mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 );
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001160
1161 /*
1162 * For subtraction, -Q.Y should have been used instead of Q.Y,
1163 * so we replace T2 by -T2, which is P - T2 mod P
1164 */
1165 if( sign < 0 )
1166 {
1167 MPI_CHK( mpi_sub_mpi( &T2, &grp->P, &T2 ) );
1168 MOD_SUB( T2 );
1169 }
1170
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001171 MPI_CHK( mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 );
1172 MPI_CHK( mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001173
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001174 if( mpi_cmp_int( &T1, 0 ) == 0 )
1175 {
1176 if( mpi_cmp_int( &T2, 0 ) == 0 )
1177 {
1178 ret = ecp_double_jac( grp, R, P );
1179 goto cleanup;
1180 }
1181 else
1182 {
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001183 ret = ecp_set_zero( R );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001184 goto cleanup;
1185 }
1186 }
1187
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001188 MPI_CHK( mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z );
1189 MPI_CHK( mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 );
1190 MPI_CHK( mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 );
1191 MPI_CHK( mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 );
1192 MPI_CHK( mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 );
1193 MPI_CHK( mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X );
1194 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X );
1195 MPI_CHK( mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X );
1196 MPI_CHK( mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 );
1197 MPI_CHK( mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 );
1198 MPI_CHK( mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 );
1199 MPI_CHK( mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y );
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001200
Manuel Pégourié-Gonnard84d1aea2012-11-09 02:09:38 +01001201 MPI_CHK( mpi_copy( &R->X, &X ) );
1202 MPI_CHK( mpi_copy( &R->Y, &Y ) );
1203 MPI_CHK( mpi_copy( &R->Z, &Z ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001204
1205cleanup:
1206
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001207 mpi_free( &T1 ); mpi_free( &T2 ); mpi_free( &T3 ); mpi_free( &T4 );
1208 mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001209
1210 return( ret );
1211}
1212
1213/*
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001214 * Addition: R = P + Q, result's coordinates normalized
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001215 */
1216int ecp_add( const ecp_group *grp, ecp_point *R,
1217 const ecp_point *P, const ecp_point *Q )
1218{
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001219 int ret;
Manuel Pégourié-Gonnard989c32b2012-11-08 22:02:42 +01001220
Manuel Pégourié-Gonnard9674fd02012-11-19 21:23:27 +01001221 MPI_CHK( ecp_add_mixed( grp, R, P, Q , 1 ) );
1222 MPI_CHK( ecp_normalize( grp, R ) );
1223
1224cleanup:
1225 return( ret );
1226}
1227
1228/*
1229 * Subtraction: R = P - Q, result's coordinates normalized
1230 */
1231int ecp_sub( const ecp_group *grp, ecp_point *R,
1232 const ecp_point *P, const ecp_point *Q )
1233{
1234 int ret;
1235
1236 MPI_CHK( ecp_add_mixed( grp, R, P, Q, -1 ) );
Manuel Pégourié-Gonnard1c2782c2012-11-19 20:16:28 +01001237 MPI_CHK( ecp_normalize( grp, R ) );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001238
Manuel Pégourié-Gonnard989c32b2012-11-08 22:02:42 +01001239cleanup:
Manuel Pégourié-Gonnard7e0adfb2012-11-08 23:21:46 +01001240 return( ret );
Manuel Pégourié-Gonnardae180d02012-11-02 18:14:40 +01001241}
1242
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001243/*
Manuel Pégourié-Gonnard85556072012-11-17 19:54:20 +01001244 * Compute a modified width-w non-adjacent form (NAF) of a number,
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001245 * with a fixed pattern for resistance to simple timing attacks (even SPA),
1246 * see [1]. (The resulting multiplication algorithm can also been seen as a
1247 * modification of 2^w-ary multiplication, with signed coefficients, all of
1248 * them odd.)
Manuel Pégourié-Gonnard85556072012-11-17 19:54:20 +01001249 *
1250 * Input:
1251 * m must be an odd positive mpi less than w * k bits long
1252 * x must be an array of k elements
1253 * w must be less than a certain maximum (currently 8)
1254 *
1255 * The result is a sequence x[0], ..., x[k-1] with x[i] in the range
1256 * - 2^(width - 1) .. 2^(width - 1) - 1 such that
1257 * m = (2 * x[0] + 1) + 2^width * (2 * x[1] + 1) + ...
1258 * + 2^((k-1) * width) * (2 * x[k-1] + 1)
1259 *
1260 * Compared to "Algorithm SPA-resistant Width-w NAF with Odd Scalar"
1261 * p. 335 of the cited reference, here we return only u, not d_w since
1262 * it is known that the other d_w[j] will be 0. Moreover, the returned
1263 * string doesn't actually store u_i but x_i = u_i / 2 since it is known
1264 * that u_i is odd. Also, since we always select a positive value for d
1265 * mod 2^w, we don't need to check the sign of u[i-1] when the reference
1266 * does. Finally, there is an off-by-one error in the reference: the
1267 * last index should be k-1, not k.
1268 */
Manuel Pégourié-Gonnard7652a592012-11-21 10:00:45 +01001269static int ecp_w_naf_fixed( signed char x[], size_t k,
1270 unsigned char w, const mpi *m )
Manuel Pégourié-Gonnard85556072012-11-17 19:54:20 +01001271{
1272 int ret;
1273 unsigned int i, u, mask, carry;
1274 mpi M;
1275
1276 mpi_init( &M );
1277
1278 MPI_CHK( mpi_copy( &M, m ) );
1279 mask = ( 1 << w ) - 1;
1280 carry = 1 << ( w - 1 );
1281
1282 for( i = 0; i < k; i++ )
1283 {
1284 u = M.p[0] & mask;
1285
1286 if( ( u & 1 ) == 0 && i > 0 )
1287 x[i - 1] -= carry;
1288
1289 x[i] = u >> 1;
1290 mpi_shift_r( &M, w );
1291 }
1292
1293 /*
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001294 * We should have consumed all bits, unless the input value was too big
Manuel Pégourié-Gonnard85556072012-11-17 19:54:20 +01001295 */
1296 if( mpi_cmp_int( &M, 0 ) != 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001297 ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard85556072012-11-17 19:54:20 +01001298
1299cleanup:
1300
1301 mpi_free( &M );
1302
1303 return( ret );
1304}
1305
1306/*
Manuel Pégourié-Gonnard7652a592012-11-21 10:00:45 +01001307 * Precompute odd multiples of P up to (2 * t_len - 1) P.
1308 * The table is filled with T[i] = (2 * i + 1) P.
1309 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001310static int ecp_precompute( const ecp_group *grp,
1311 ecp_point T[], size_t t_len,
1312 const ecp_point *P )
Manuel Pégourié-Gonnard7652a592012-11-21 10:00:45 +01001313{
1314 int ret;
1315 size_t i;
1316 ecp_point PP;
1317
1318 ecp_point_init( &PP );
1319
1320 MPI_CHK( ecp_add( grp, &PP, P, P ) );
1321
1322 MPI_CHK( ecp_copy( &T[0], P ) );
1323
Manuel Pégourié-Gonnard7652a592012-11-21 10:00:45 +01001324 for( i = 1; i < t_len; i++ )
Manuel Pégourié-Gonnardcdd44322012-11-21 16:00:55 +01001325 MPI_CHK( ecp_add_mixed( grp, &T[i], &T[i-1], &PP, +1 ) );
1326
1327 /*
1328 * T[0] = P already has normalized coordinates
1329 */
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001330 MPI_CHK( ecp_normalize_many( grp, T + 1, t_len - 1 ) );
Manuel Pégourié-Gonnard7652a592012-11-21 10:00:45 +01001331
1332cleanup:
1333
1334 ecp_point_free( &PP );
1335
1336 return( ret );
1337}
1338
1339/*
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001340 * Randomize jacobian coordinates:
1341 * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l
1342 * This is sort of the reverse operation of ecp_normalize().
1343 */
1344static int ecp_randomize_coordinates( const ecp_group *grp, ecp_point *pt,
1345 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
1346{
1347 int ret;
1348 mpi l, ll;
1349 size_t p_size = (grp->pbits + 7) / 8;
1350 int count = 0;
1351
1352 mpi_init( &l ); mpi_init( &ll );
1353
1354 /* Generate l such that 1 < l < p */
1355 do
1356 {
1357 mpi_fill_random( &l, p_size, f_rng, p_rng );
1358
1359 while( mpi_cmp_mpi( &l, &grp->P ) >= 0 )
1360 mpi_shift_r( &l, 1 );
1361
1362 if( count++ > 10 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001363 return( POLARSSL_ERR_ECP_RANDOM_FAILED );
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001364 }
1365 while( mpi_cmp_int( &l, 1 ) <= 0 );
1366
1367 /* Z = l * Z */
1368 MPI_CHK( mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z );
1369
1370 /* X = l^2 * X */
1371 MPI_CHK( mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll );
1372 MPI_CHK( mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X );
1373
1374 /* Y = l^3 * Y */
1375 MPI_CHK( mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll );
1376 MPI_CHK( mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y );
1377
1378cleanup:
1379 mpi_free( &l ); mpi_free( &ll );
1380
1381 return( ret );
1382}
1383
1384/*
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001385 * Maximum length of the precomputed table
1386 */
1387#define MAX_PRE_LEN ( 1 << (POLARSSL_ECP_WINDOW_SIZE - 1) )
1388
1389/*
1390 * Maximum length of the NAF: ceil( grp->nbits + 1 ) / w
1391 * (that is: grp->nbits / w + 1)
1392 * Allow p_bits + 1 bits in case M = grp->N + 1 is one bit longer than N.
1393 */
Manuel Pégourié-Gonnardb694b482013-08-08 13:30:57 +02001394#define MAX_NAF_LEN ( POLARSSL_ECP_MAX_BITS / 2 + 1 )
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001395
1396/*
1397 * Integer multiplication: R = m * P
1398 *
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001399 * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed().
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001400 *
1401 * This function executes a fixed number of operations for
1402 * random m in the range 0 .. 2^nbits - 1.
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001403 *
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001404 * As an additional countermeasure against potential timing attacks,
1405 * we randomize coordinates before each addition. This was suggested as a
Manuel Pégourié-Gonnard07de4b12013-09-02 16:26:04 +02001406 * countermeasure against DPA in 5.3 of [2] (with the obvious adaptation that
1407 * we use jacobian coordinates, not standard projective coordinates).
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001408 */
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001409int ecp_mul( ecp_group *grp, ecp_point *R,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +02001410 const mpi *m, const ecp_point *P,
1411 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001412{
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001413 int ret;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001414 unsigned char w, m_is_odd, p_eq_g;
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001415 size_t pre_len = 1, naf_len, i, j;
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001416 signed char naf[ MAX_NAF_LEN ];
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001417 ecp_point Q, *T = NULL, S[2];
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001418 mpi M;
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001419
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001420 if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits )
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +02001421 return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard4bdd47d2012-11-11 14:33:59 +01001422
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001423 mpi_init( &M );
1424 ecp_point_init( &Q );
1425 ecp_point_init( &S[0] );
1426 ecp_point_init( &S[1] );
1427
1428 /*
1429 * Check if P == G
1430 */
1431 p_eq_g = ( mpi_cmp_int( &P->Z, 1 ) == 0 &&
1432 mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
1433 mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 );
1434
1435 /*
1436 * If P == G, pre-compute a lot of points: this will be re-used later,
1437 * otherwise, choose window size depending on curve size
1438 */
1439 if( p_eq_g )
1440 w = POLARSSL_ECP_WINDOW_SIZE;
1441 else
1442 w = grp->nbits >= 512 ? 6 :
1443 grp->nbits >= 224 ? 5 :
1444 4;
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001445
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001446 /*
1447 * Make sure w is within the limits.
1448 * The last test ensures that none of the precomputed points is zero,
1449 * which wouldn't be handled correctly by ecp_normalize_many().
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001450 * It is only useful for very small curves as used in the test suite.
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001451 */
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001452 if( w > POLARSSL_ECP_WINDOW_SIZE )
1453 w = POLARSSL_ECP_WINDOW_SIZE;
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001454 if( w < 2 || w >= grp->nbits )
1455 w = 2;
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001456
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001457 pre_len <<= ( w - 1 );
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001458 naf_len = grp->nbits / w + 1;
1459
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001460 /*
1461 * Prepare precomputed points: if P == G we want to
1462 * use grp->T if already initialized, or initiliaze it.
1463 */
1464 if( ! p_eq_g || grp->T == NULL )
1465 {
Paul Bakkerb9cfaa02013-10-11 18:58:55 +02001466 T = (ecp_point *) polarssl_malloc( pre_len * sizeof( ecp_point ) );
1467 if( T == NULL )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001468 {
1469 ret = POLARSSL_ERR_ECP_MALLOC_FAILED;
1470 goto cleanup;
1471 }
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001472
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001473 for( i = 0; i < pre_len; i++ )
1474 ecp_point_init( &T[i] );
1475
1476 MPI_CHK( ecp_precompute( grp, T, pre_len, P ) );
1477
1478 if( p_eq_g )
1479 {
1480 grp->T = T;
1481 grp->T_size = pre_len;
1482 }
1483 }
1484 else
1485 {
1486 T = grp->T;
1487
1488 /* Should never happen, but we want to be extra sure */
1489 if( pre_len != grp->T_size )
1490 {
1491 ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
1492 goto cleanup;
1493 }
1494 }
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001495
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001496 /*
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001497 * Make sure M is odd (M = m + 1 or M = m + 2)
1498 * later we'll get m * P by subtracting P or 2 * P to M * P.
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001499 */
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001500 m_is_odd = ( mpi_get_bit( m, 0 ) == 1 );
1501
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001502 MPI_CHK( mpi_copy( &M, m ) );
1503 MPI_CHK( mpi_add_int( &M, &M, 1 + m_is_odd ) );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001504
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001505 /*
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001506 * Compute the fixed-pattern NAF of M
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001507 */
1508 MPI_CHK( ecp_w_naf_fixed( naf, naf_len, w, &M ) );
Manuel Pégourié-Gonnard47123252012-11-10 14:44:24 +01001509
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001510 /*
1511 * Compute M * P, using a variant of left-to-right 2^w-ary multiplication:
1512 * at each step we add (2 * naf[i] + 1) P, then multiply by 2^w.
1513 *
1514 * If naf[i] >= 0, we have (2 * naf[i] + 1) P == T[ naf[i] ]
1515 * Otherwise, (2 * naf[i] + 1) P == - ( 2 * ( - naf[i] - 1 ) + 1) P
1516 * == T[ - naf[i] - 1 ]
1517 */
1518 MPI_CHK( ecp_set_zero( &Q ) );
1519 i = naf_len - 1;
1520 while( 1 )
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001521 {
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001522 /* Countermeasure (see comments above) */
1523 if( f_rng != NULL )
1524 ecp_randomize_coordinates( grp, &Q, f_rng, p_rng );
1525
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001526 if( naf[i] < 0 )
1527 {
1528 MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ - naf[i] - 1 ], -1 ) );
1529 }
1530 else
1531 {
1532 MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ naf[i] ], +1 ) );
1533 }
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001534
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001535 if( i == 0 )
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001536 break;
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001537 i--;
1538
1539 for( j = 0; j < w; j++ )
1540 {
1541 MPI_CHK( ecp_double_jac( grp, &Q, &Q ) );
1542 }
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001543 }
1544
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001545 /*
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001546 * Now get m * P from M * P
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001547 */
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001548 MPI_CHK( ecp_copy( &S[0], P ) );
1549 MPI_CHK( ecp_add( grp, &S[1], P, P ) );
1550 MPI_CHK( ecp_sub( grp, R, &Q, &S[m_is_odd] ) );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001551
Manuel Pégourié-Gonnard3680c822012-11-21 18:49:45 +01001552
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001553cleanup:
1554
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001555 if( T != NULL && ! p_eq_g )
1556 {
1557 for( i = 0; i < pre_len; i++ )
1558 ecp_point_free( &T[i] );
1559 polarssl_free( T );
1560 }
1561
1562 ecp_point_free( &S[1] );
1563 ecp_point_free( &S[0] );
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001564 ecp_point_free( &Q );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001565 mpi_free( &M );
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001566
1567 return( ret );
1568}
1569
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01001570/*
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001571 * Check that a point is valid as a public key (SEC1 3.2.3.1)
1572 */
1573int ecp_check_pubkey( const ecp_group *grp, const ecp_point *pt )
1574{
1575 int ret;
1576 mpi YY, RHS;
1577
1578 if( mpi_cmp_int( &pt->Z, 0 ) == 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001579 return( POLARSSL_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001580
1581 /*
1582 * pt coordinates must be normalized for our checks
1583 */
1584 if( mpi_cmp_int( &pt->Z, 1 ) != 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001585 return( POLARSSL_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001586
1587 if( mpi_cmp_int( &pt->X, 0 ) < 0 ||
1588 mpi_cmp_int( &pt->Y, 0 ) < 0 ||
1589 mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 ||
1590 mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001591 return( POLARSSL_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001592
1593 mpi_init( &YY ); mpi_init( &RHS );
1594
1595 /*
1596 * YY = Y^2
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02001597 * RHS = X (X^2 + A) + B = X^3 + A X + B
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001598 */
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02001599 MPI_CHK( mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY );
1600 MPI_CHK( mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS );
Manuel Pégourié-Gonnard0cd6f982013-10-10 15:55:39 +02001601 MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardcd7458a2013-10-08 13:11:30 +02001602 MPI_CHK( mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS );
1603 MPI_CHK( mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001604
1605 if( mpi_cmp_mpi( &YY, &RHS ) != 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001606 ret = POLARSSL_ERR_ECP_INVALID_KEY;
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001607
1608cleanup:
1609
1610 mpi_free( &YY ); mpi_free( &RHS );
1611
1612 return( ret );
1613}
1614
1615/*
1616 * Check that an mpi is valid as a private key (SEC1 3.2)
1617 */
Manuel Pégourié-Gonnardde44a4a2013-07-09 16:05:52 +02001618int ecp_check_privkey( const ecp_group *grp, const mpi *d )
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001619{
1620 /* We want 1 <= d <= N-1 */
1621 if ( mpi_cmp_int( d, 1 ) < 0 || mpi_cmp_mpi( d, &grp->N ) >= 0 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001622 return( POLARSSL_ERR_ECP_INVALID_KEY );
Manuel Pégourié-Gonnardc8dc2952013-07-01 14:06:13 +02001623
1624 return( 0 );
1625}
1626
1627/*
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01001628 * Generate a keypair (SEC1 3.2.1)
1629 */
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001630int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q,
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01001631 int (*f_rng)(void *, unsigned char *, size_t),
1632 void *p_rng )
1633{
1634 int count = 0;
1635 size_t n_size = (grp->nbits + 7) / 8;
1636
1637 /*
1638 * Generate d such that 1 <= n < N
1639 */
1640 do
1641 {
1642 mpi_fill_random( d, n_size, f_rng, p_rng );
1643
1644 while( mpi_cmp_mpi( d, &grp->N ) >= 0 )
1645 mpi_shift_r( d, 1 );
1646
1647 if( count++ > 10 )
Manuel Pégourié-Gonnard456d3b92013-09-16 18:04:38 +02001648 return( POLARSSL_ERR_ECP_RANDOM_FAILED );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01001649 }
1650 while( mpi_cmp_int( d, 1 ) < 0 );
1651
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +02001652 return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
Manuel Pégourié-Gonnard45a035a2013-01-26 14:42:45 +01001653}
Manuel Pégourié-Gonnardefaa31e2012-11-06 21:34:35 +01001654
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001655#if defined(POLARSSL_SELF_TEST)
1656
Manuel Pégourié-Gonnardb505c272012-11-05 17:27:54 +01001657/*
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001658 * Checkup routine
1659 */
1660int ecp_self_test( int verbose )
1661{
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001662 int ret;
1663 size_t i;
1664 ecp_group grp;
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001665 ecp_point R, P;
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001666 mpi m;
1667 unsigned long add_c_prev, dbl_c_prev;
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02001668 /* exponents especially adapted for secp192r1 */
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +02001669 const char *exponents[] =
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001670 {
Manuel Pégourié-Gonnardb63f9e92012-11-21 13:00:58 +01001671 "000000000000000000000000000000000000000000000000", /* zero */
1672 "000000000000000000000000000000000000000000000001", /* one */
1673 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* N */
1674 "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001675 "400000000000000000000000000000000000000000000000",
1676 "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
1677 "555555555555555555555555555555555555555555555555",
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001678 };
1679
1680 ecp_group_init( &grp );
1681 ecp_point_init( &R );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001682 ecp_point_init( &P );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001683 mpi_init( &m );
1684
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02001685 /* Use secp192r1 if available, or any available curve */
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02001686#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001687 MPI_CHK( ecp_use_known_dp( &grp, POLARSSL_ECP_DP_SECP192R1 ) );
Paul Bakker5dc6b5f2013-06-29 23:26:34 +02001688#else
Manuel Pégourié-Gonnardb8012fc2013-10-10 15:40:49 +02001689 MPI_CHK( ecp_use_known_dp( &grp, ecp_curve_list()->grp_id ) );
1690#endif
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001691
1692 if( verbose != 0 )
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001693 printf( " ECP test #1 (constant op_count, base point G): " );
1694
1695 /* Do a dummy multiplication first to trigger precomputation */
1696 MPI_CHK( mpi_lset( &m, 2 ) );
1697 MPI_CHK( ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001698
1699 add_count = 0;
1700 dbl_count = 0;
1701 MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +02001702 MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001703
1704 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
1705 {
1706 add_c_prev = add_count;
1707 dbl_c_prev = dbl_count;
1708 add_count = 0;
1709 dbl_count = 0;
1710
1711 MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +02001712 MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001713
1714 if( add_count != add_c_prev || dbl_count != dbl_c_prev )
1715 {
1716 if( verbose != 0 )
1717 printf( "failed (%zu)\n", i );
1718
1719 ret = 1;
1720 goto cleanup;
1721 }
1722 }
1723
1724 if( verbose != 0 )
1725 printf( "passed\n" );
1726
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001727 if( verbose != 0 )
1728 printf( " ECP test #2 (constant op_count, other point): " );
1729 /* We computed P = 2G last time, use it */
1730
1731 add_count = 0;
1732 dbl_count = 0;
1733 MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
1734 MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
1735
1736 for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
1737 {
1738 add_c_prev = add_count;
1739 dbl_c_prev = dbl_count;
1740 add_count = 0;
1741 dbl_count = 0;
1742
1743 MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
1744 MPI_CHK( ecp_mul( &grp, &R, &m, &P, NULL, NULL ) );
1745
1746 if( add_count != add_c_prev || dbl_count != dbl_c_prev )
1747 {
1748 if( verbose != 0 )
1749 printf( "failed (%zu)\n", i );
1750
1751 ret = 1;
1752 goto cleanup;
1753 }
1754 }
1755
1756 if( verbose != 0 )
1757 printf( "passed\n" );
1758
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001759cleanup:
1760
1761 if( ret < 0 && verbose != 0 )
1762 printf( "Unexpected error, return code = %08X\n", ret );
1763
1764 ecp_group_free( &grp );
1765 ecp_point_free( &R );
Manuel Pégourié-Gonnard161ef962013-09-17 19:13:10 +02001766 ecp_point_free( &P );
Manuel Pégourié-Gonnardb4a310b2012-11-13 20:57:00 +01001767 mpi_free( &m );
1768
1769 if( verbose != 0 )
1770 printf( "\n" );
1771
1772 return( ret );
Manuel Pégourié-Gonnard39d2adb2012-10-31 09:26:55 +01001773}
1774
1775#endif
1776
1777#endif