blob: 4f5bb434c45d0c1eacf59eb3b748bec3c509941b [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Multi-precision integer library
3 *
Paul Bakker84f12b72010-07-18 10:13:04 +00004 * Copyright (C) 2006-2010, Brainspark B.V.
5 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
Paul Bakker77b385e2009-07-28 17:23:11 +00006 * All rights reserved.
Paul Bakkere0ccd0a2009-01-04 16:27:10 +00007 *
Paul Bakker5121ce52009-01-03 21:22:43 +00008 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22/*
23 * This MPI implementation is based on:
24 *
25 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
26 * http://www.stillhq.com/extracted/gnupg-api/mpi/
27 * http://math.libtomcrypt.com/files/tommath.pdf
28 */
29
Paul Bakker40e46942009-01-03 21:51:57 +000030#include "polarssl/config.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Paul Bakker40e46942009-01-03 21:51:57 +000032#if defined(POLARSSL_BIGNUM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Paul Bakker40e46942009-01-03 21:51:57 +000034#include "polarssl/bignum.h"
35#include "polarssl/bn_mul.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000036
37#include <string.h>
38#include <stdlib.h>
39#include <stdarg.h>
40
41#define ciL ((int) sizeof(t_int)) /* chars in limb */
42#define biL (ciL << 3) /* bits in limb */
43#define biH (ciL << 2) /* half limb size */
44
45/*
46 * Convert between bits/chars and number of limbs
47 */
48#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
49#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
50
51/*
52 * Initialize one or more mpi
53 */
54void mpi_init( mpi *X, ... )
55{
56 va_list args;
57
58 va_start( args, X );
59
60 while( X != NULL )
61 {
62 X->s = 1;
63 X->n = 0;
64 X->p = NULL;
65
66 X = va_arg( args, mpi* );
67 }
68
69 va_end( args );
70}
71
72/*
73 * Unallocate one or more mpi
74 */
75void mpi_free( mpi *X, ... )
76{
77 va_list args;
78
79 va_start( args, X );
80
81 while( X != NULL )
82 {
83 if( X->p != NULL )
84 {
85 memset( X->p, 0, X->n * ciL );
86 free( X->p );
87 }
88
89 X->s = 1;
90 X->n = 0;
91 X->p = NULL;
92
93 X = va_arg( args, mpi* );
94 }
95
96 va_end( args );
97}
98
99/*
100 * Enlarge to the specified number of limbs
101 */
102int mpi_grow( mpi *X, int nblimbs )
103{
104 t_int *p;
105
106 if( X->n < nblimbs )
107 {
108 if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL )
109 return( 1 );
110
111 memset( p, 0, nblimbs * ciL );
112
113 if( X->p != NULL )
114 {
115 memcpy( p, X->p, X->n * ciL );
116 memset( X->p, 0, X->n * ciL );
117 free( X->p );
118 }
119
120 X->n = nblimbs;
121 X->p = p;
122 }
123
124 return( 0 );
125}
126
127/*
128 * Copy the contents of Y into X
129 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000130int mpi_copy( mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000131{
132 int ret, i;
133
134 if( X == Y )
135 return( 0 );
136
137 for( i = Y->n - 1; i > 0; i-- )
138 if( Y->p[i] != 0 )
139 break;
140 i++;
141
142 X->s = Y->s;
143
144 MPI_CHK( mpi_grow( X, i ) );
145
146 memset( X->p, 0, X->n * ciL );
147 memcpy( X->p, Y->p, i * ciL );
148
149cleanup:
150
151 return( ret );
152}
153
154/*
155 * Swap the contents of X and Y
156 */
157void mpi_swap( mpi *X, mpi *Y )
158{
159 mpi T;
160
161 memcpy( &T, X, sizeof( mpi ) );
162 memcpy( X, Y, sizeof( mpi ) );
163 memcpy( Y, &T, sizeof( mpi ) );
164}
165
166/*
167 * Set value from integer
168 */
169int mpi_lset( mpi *X, int z )
170{
171 int ret;
172
173 MPI_CHK( mpi_grow( X, 1 ) );
174 memset( X->p, 0, X->n * ciL );
175
176 X->p[0] = ( z < 0 ) ? -z : z;
177 X->s = ( z < 0 ) ? -1 : 1;
178
179cleanup:
180
181 return( ret );
182}
183
184/*
185 * Return the number of least significant bits
186 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000187int mpi_lsb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000188{
189 int i, j, count = 0;
190
191 for( i = 0; i < X->n; i++ )
192 for( j = 0; j < (int) biL; j++, count++ )
193 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
194 return( count );
195
196 return( 0 );
197}
198
199/*
200 * Return the number of most significant bits
201 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000202int mpi_msb( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000203{
204 int i, j;
205
206 for( i = X->n - 1; i > 0; i-- )
207 if( X->p[i] != 0 )
208 break;
209
210 for( j = biL - 1; j >= 0; j-- )
211 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
212 break;
213
214 return( ( i * biL ) + j + 1 );
215}
216
217/*
218 * Return the total size in bytes
219 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000220int mpi_size( const mpi *X )
Paul Bakker5121ce52009-01-03 21:22:43 +0000221{
222 return( ( mpi_msb( X ) + 7 ) >> 3 );
223}
224
225/*
226 * Convert an ASCII character to digit value
227 */
228static int mpi_get_digit( t_int *d, int radix, char c )
229{
230 *d = 255;
231
232 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
233 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
234 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
235
236 if( *d >= (t_int) radix )
Paul Bakker40e46942009-01-03 21:51:57 +0000237 return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
239 return( 0 );
240}
241
242/*
243 * Import from an ASCII string
244 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000245int mpi_read_string( mpi *X, int radix, const char *s )
Paul Bakker5121ce52009-01-03 21:22:43 +0000246{
Paul Bakkerff60ee62010-03-16 21:09:09 +0000247 int ret, i, j, n, slen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000248 t_int d;
249 mpi T;
250
251 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000252 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000253
254 mpi_init( &T, NULL );
255
Paul Bakkerff60ee62010-03-16 21:09:09 +0000256 slen = strlen( s );
257
Paul Bakker5121ce52009-01-03 21:22:43 +0000258 if( radix == 16 )
259 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000260 n = BITS_TO_LIMBS( slen << 2 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000261
262 MPI_CHK( mpi_grow( X, n ) );
263 MPI_CHK( mpi_lset( X, 0 ) );
264
Paul Bakkerff60ee62010-03-16 21:09:09 +0000265 for( i = slen - 1, j = 0; i >= 0; i--, j++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000266 {
267 if( i == 0 && s[i] == '-' )
268 {
269 X->s = -1;
270 break;
271 }
272
273 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
274 X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
275 }
276 }
277 else
278 {
279 MPI_CHK( mpi_lset( X, 0 ) );
280
Paul Bakkerff60ee62010-03-16 21:09:09 +0000281 for( i = 0; i < slen; i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000282 {
283 if( i == 0 && s[i] == '-' )
284 {
285 X->s = -1;
286 continue;
287 }
288
289 MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
290 MPI_CHK( mpi_mul_int( &T, X, radix ) );
Paul Bakker05feca62009-06-20 08:22:43 +0000291
292 if( X->s == 1 )
293 {
294 MPI_CHK( mpi_add_int( X, &T, d ) );
295 }
296 else
297 {
298 MPI_CHK( mpi_sub_int( X, &T, d ) );
299 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000300 }
301 }
302
303cleanup:
304
305 mpi_free( &T, NULL );
306
307 return( ret );
308}
309
310/*
311 * Helper to write the digits high-order first
312 */
313static int mpi_write_hlp( mpi *X, int radix, char **p )
314{
315 int ret;
316 t_int r;
317
318 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000319 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000320
321 MPI_CHK( mpi_mod_int( &r, X, radix ) );
322 MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
323
324 if( mpi_cmp_int( X, 0 ) != 0 )
325 MPI_CHK( mpi_write_hlp( X, radix, p ) );
326
327 if( r < 10 )
328 *(*p)++ = (char)( r + 0x30 );
329 else
330 *(*p)++ = (char)( r + 0x37 );
331
332cleanup:
333
334 return( ret );
335}
336
337/*
338 * Export into an ASCII string
339 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000340int mpi_write_string( const mpi *X, int radix, char *s, int *slen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000341{
342 int ret = 0, n;
343 char *p;
344 mpi T;
345
346 if( radix < 2 || radix > 16 )
Paul Bakker40e46942009-01-03 21:51:57 +0000347 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000348
349 n = mpi_msb( X );
350 if( radix >= 4 ) n >>= 1;
351 if( radix >= 16 ) n >>= 1;
352 n += 3;
353
354 if( *slen < n )
355 {
356 *slen = n;
Paul Bakker40e46942009-01-03 21:51:57 +0000357 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000358 }
359
360 p = s;
361 mpi_init( &T, NULL );
362
363 if( X->s == -1 )
364 *p++ = '-';
365
366 if( radix == 16 )
367 {
368 int c, i, j, k;
369
370 for( i = X->n - 1, k = 0; i >= 0; i-- )
371 {
372 for( j = ciL - 1; j >= 0; j-- )
373 {
374 c = ( X->p[i] >> (j << 3) ) & 0xFF;
375
376 if( c == 0 && k == 0 && (i + j) != 0 )
377 continue;
378
379 p += sprintf( p, "%02X", c );
380 k = 1;
381 }
382 }
383 }
384 else
385 {
386 MPI_CHK( mpi_copy( &T, X ) );
Paul Bakkerce40a6d2009-06-23 19:46:08 +0000387
388 if( T.s == -1 )
389 T.s = 1;
390
Paul Bakker5121ce52009-01-03 21:22:43 +0000391 MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
392 }
393
394 *p++ = '\0';
395 *slen = p - s;
396
397cleanup:
398
399 mpi_free( &T, NULL );
400
401 return( ret );
402}
403
404/*
405 * Read X from an opened file
406 */
407int mpi_read_file( mpi *X, int radix, FILE *fin )
408{
409 t_int d;
410 int slen;
411 char *p;
412 char s[1024];
413
414 memset( s, 0, sizeof( s ) );
415 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
Paul Bakker40e46942009-01-03 21:51:57 +0000416 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
418 slen = strlen( s );
419 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
420 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
421
422 p = s + slen;
423 while( --p >= s )
424 if( mpi_get_digit( &d, radix, *p ) != 0 )
425 break;
426
427 return( mpi_read_string( X, radix, p + 1 ) );
428}
429
430/*
431 * Write X into an opened file (or stdout if fout == NULL)
432 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000433int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
Paul Bakker5121ce52009-01-03 21:22:43 +0000434{
435 int n, ret;
436 size_t slen;
437 size_t plen;
Paul Bakker08f3c302010-07-08 06:54:25 +0000438 char s[2048];
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 n = sizeof( s );
441 memset( s, 0, n );
442 n -= 2;
443
444 MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );
445
446 if( p == NULL ) p = "";
447
448 plen = strlen( p );
449 slen = strlen( s );
450 s[slen++] = '\r';
451 s[slen++] = '\n';
452
453 if( fout != NULL )
454 {
455 if( fwrite( p, 1, plen, fout ) != plen ||
456 fwrite( s, 1, slen, fout ) != slen )
Paul Bakker40e46942009-01-03 21:51:57 +0000457 return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458 }
459 else
460 printf( "%s%s", p, s );
461
462cleanup:
463
464 return( ret );
465}
466
467/*
468 * Import X from unsigned binary data, big endian
469 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000470int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000471{
472 int ret, i, j, n;
473
474 for( n = 0; n < buflen; n++ )
475 if( buf[n] != 0 )
476 break;
477
478 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
479 MPI_CHK( mpi_lset( X, 0 ) );
480
481 for( i = buflen - 1, j = 0; i >= n; i--, j++ )
482 X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);
483
484cleanup:
485
486 return( ret );
487}
488
489/*
490 * Export X into unsigned binary data, big endian
491 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000492int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000493{
494 int i, j, n;
495
496 n = mpi_size( X );
497
498 if( buflen < n )
Paul Bakker40e46942009-01-03 21:51:57 +0000499 return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000500
501 memset( buf, 0, buflen );
502
503 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
504 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
505
506 return( 0 );
507}
508
509/*
510 * Left-shift: X <<= count
511 */
512int mpi_shift_l( mpi *X, int count )
513{
514 int ret, i, v0, t1;
515 t_int r0 = 0, r1;
516
517 v0 = count / (biL );
518 t1 = count & (biL - 1);
519
520 i = mpi_msb( X ) + count;
521
522 if( X->n * (int) biL < i )
523 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
524
525 ret = 0;
526
527 /*
528 * shift by count / limb_size
529 */
530 if( v0 > 0 )
531 {
532 for( i = X->n - 1; i >= v0; i-- )
533 X->p[i] = X->p[i - v0];
534
535 for( ; i >= 0; i-- )
536 X->p[i] = 0;
537 }
538
539 /*
540 * shift by count % limb_size
541 */
542 if( t1 > 0 )
543 {
544 for( i = v0; i < X->n; i++ )
545 {
546 r1 = X->p[i] >> (biL - t1);
547 X->p[i] <<= t1;
548 X->p[i] |= r0;
549 r0 = r1;
550 }
551 }
552
553cleanup:
554
555 return( ret );
556}
557
558/*
559 * Right-shift: X >>= count
560 */
561int mpi_shift_r( mpi *X, int count )
562{
563 int i, v0, v1;
564 t_int r0 = 0, r1;
565
566 v0 = count / biL;
567 v1 = count & (biL - 1);
568
569 /*
570 * shift by count / limb_size
571 */
572 if( v0 > 0 )
573 {
574 for( i = 0; i < X->n - v0; i++ )
575 X->p[i] = X->p[i + v0];
576
577 for( ; i < X->n; i++ )
578 X->p[i] = 0;
579 }
580
581 /*
582 * shift by count % limb_size
583 */
584 if( v1 > 0 )
585 {
586 for( i = X->n - 1; i >= 0; i-- )
587 {
588 r1 = X->p[i] << (biL - v1);
589 X->p[i] >>= v1;
590 X->p[i] |= r0;
591 r0 = r1;
592 }
593 }
594
595 return( 0 );
596}
597
598/*
599 * Compare unsigned values
600 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000601int mpi_cmp_abs( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000602{
603 int i, j;
604
605 for( i = X->n - 1; i >= 0; i-- )
606 if( X->p[i] != 0 )
607 break;
608
609 for( j = Y->n - 1; j >= 0; j-- )
610 if( Y->p[j] != 0 )
611 break;
612
613 if( i < 0 && j < 0 )
614 return( 0 );
615
616 if( i > j ) return( 1 );
617 if( j > i ) return( -1 );
618
619 for( ; i >= 0; i-- )
620 {
621 if( X->p[i] > Y->p[i] ) return( 1 );
622 if( X->p[i] < Y->p[i] ) return( -1 );
623 }
624
625 return( 0 );
626}
627
628/*
629 * Compare signed values
630 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000631int mpi_cmp_mpi( const mpi *X, const mpi *Y )
Paul Bakker5121ce52009-01-03 21:22:43 +0000632{
633 int i, j;
634
635 for( i = X->n - 1; i >= 0; i-- )
636 if( X->p[i] != 0 )
637 break;
638
639 for( j = Y->n - 1; j >= 0; j-- )
640 if( Y->p[j] != 0 )
641 break;
642
643 if( i < 0 && j < 0 )
644 return( 0 );
645
646 if( i > j ) return( X->s );
647 if( j > i ) return( -X->s );
648
649 if( X->s > 0 && Y->s < 0 ) return( 1 );
650 if( Y->s > 0 && X->s < 0 ) return( -1 );
651
652 for( ; i >= 0; i-- )
653 {
654 if( X->p[i] > Y->p[i] ) return( X->s );
655 if( X->p[i] < Y->p[i] ) return( -X->s );
656 }
657
658 return( 0 );
659}
660
661/*
662 * Compare signed values
663 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000664int mpi_cmp_int( const mpi *X, int z )
Paul Bakker5121ce52009-01-03 21:22:43 +0000665{
666 mpi Y;
667 t_int p[1];
668
669 *p = ( z < 0 ) ? -z : z;
670 Y.s = ( z < 0 ) ? -1 : 1;
671 Y.n = 1;
672 Y.p = p;
673
674 return( mpi_cmp_mpi( X, &Y ) );
675}
676
677/*
678 * Unsigned addition: X = |A| + |B| (HAC 14.7)
679 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000680int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681{
682 int ret, i, j;
683 t_int *o, *p, c;
684
685 if( X == B )
686 {
Paul Bakkerff60ee62010-03-16 21:09:09 +0000687 const mpi *T = A; A = X; B = T;
Paul Bakker5121ce52009-01-03 21:22:43 +0000688 }
689
690 if( X != A )
691 MPI_CHK( mpi_copy( X, A ) );
Paul Bakkerf7ca7b92009-06-20 10:31:06 +0000692
693 /*
694 * X should always be positive as a result of unsigned additions.
695 */
696 X->s = 1;
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
698 for( j = B->n - 1; j >= 0; j-- )
699 if( B->p[j] != 0 )
700 break;
701
702 MPI_CHK( mpi_grow( X, j + 1 ) );
703
704 o = B->p; p = X->p; c = 0;
705
706 for( i = 0; i <= j; i++, o++, p++ )
707 {
708 *p += c; c = ( *p < c );
709 *p += *o; c += ( *p < *o );
710 }
711
712 while( c != 0 )
713 {
714 if( i >= X->n )
715 {
716 MPI_CHK( mpi_grow( X, i + 1 ) );
717 p = X->p + i;
718 }
719
720 *p += c; c = ( *p < c ); i++;
721 }
722
723cleanup:
724
725 return( ret );
726}
727
728/*
729 * Helper for mpi substraction
730 */
731static void mpi_sub_hlp( int n, t_int *s, t_int *d )
732{
733 int i;
734 t_int c, z;
735
736 for( i = c = 0; i < n; i++, s++, d++ )
737 {
738 z = ( *d < c ); *d -= c;
739 c = ( *d < *s ) + z; *d -= *s;
740 }
741
742 while( c != 0 )
743 {
744 z = ( *d < c ); *d -= c;
745 c = z; i++; d++;
746 }
747}
748
749/*
750 * Unsigned substraction: X = |A| - |B| (HAC 14.9)
751 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000752int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753{
754 mpi TB;
755 int ret, n;
756
757 if( mpi_cmp_abs( A, B ) < 0 )
Paul Bakker40e46942009-01-03 21:51:57 +0000758 return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
Paul Bakker5121ce52009-01-03 21:22:43 +0000759
760 mpi_init( &TB, NULL );
761
762 if( X == B )
763 {
764 MPI_CHK( mpi_copy( &TB, B ) );
765 B = &TB;
766 }
767
768 if( X != A )
769 MPI_CHK( mpi_copy( X, A ) );
770
Paul Bakker1ef7a532009-06-20 10:50:55 +0000771 /*
772 * X should always be positive as a result of unsigned substractions.
773 */
774 X->s = 1;
775
Paul Bakker5121ce52009-01-03 21:22:43 +0000776 ret = 0;
777
778 for( n = B->n - 1; n >= 0; n-- )
779 if( B->p[n] != 0 )
780 break;
781
782 mpi_sub_hlp( n + 1, B->p, X->p );
783
784cleanup:
785
786 mpi_free( &TB, NULL );
787
788 return( ret );
789}
790
791/*
792 * Signed addition: X = A + B
793 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000794int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000795{
796 int ret, s = A->s;
797
798 if( A->s * B->s < 0 )
799 {
800 if( mpi_cmp_abs( A, B ) >= 0 )
801 {
802 MPI_CHK( mpi_sub_abs( X, A, B ) );
803 X->s = s;
804 }
805 else
806 {
807 MPI_CHK( mpi_sub_abs( X, B, A ) );
808 X->s = -s;
809 }
810 }
811 else
812 {
813 MPI_CHK( mpi_add_abs( X, A, B ) );
814 X->s = s;
815 }
816
817cleanup:
818
819 return( ret );
820}
821
822/*
823 * Signed substraction: X = A - B
824 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000825int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000826{
827 int ret, s = A->s;
828
829 if( A->s * B->s > 0 )
830 {
831 if( mpi_cmp_abs( A, B ) >= 0 )
832 {
833 MPI_CHK( mpi_sub_abs( X, A, B ) );
834 X->s = s;
835 }
836 else
837 {
838 MPI_CHK( mpi_sub_abs( X, B, A ) );
839 X->s = -s;
840 }
841 }
842 else
843 {
844 MPI_CHK( mpi_add_abs( X, A, B ) );
845 X->s = s;
846 }
847
848cleanup:
849
850 return( ret );
851}
852
853/*
854 * Signed addition: X = A + b
855 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000856int mpi_add_int( mpi *X, const mpi *A, int b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000857{
858 mpi _B;
859 t_int p[1];
860
861 p[0] = ( b < 0 ) ? -b : b;
862 _B.s = ( b < 0 ) ? -1 : 1;
863 _B.n = 1;
864 _B.p = p;
865
866 return( mpi_add_mpi( X, A, &_B ) );
867}
868
869/*
870 * Signed substraction: X = A - b
871 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000872int mpi_sub_int( mpi *X, const mpi *A, int b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000873{
874 mpi _B;
875 t_int p[1];
876
877 p[0] = ( b < 0 ) ? -b : b;
878 _B.s = ( b < 0 ) ? -1 : 1;
879 _B.n = 1;
880 _B.p = p;
881
882 return( mpi_sub_mpi( X, A, &_B ) );
883}
884
885/*
886 * Helper for mpi multiplication
887 */
888static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
889{
890 t_int c = 0, t = 0;
891
892#if defined(MULADDC_HUIT)
893 for( ; i >= 8; i -= 8 )
894 {
895 MULADDC_INIT
896 MULADDC_HUIT
897 MULADDC_STOP
898 }
899
900 for( ; i > 0; i-- )
901 {
902 MULADDC_INIT
903 MULADDC_CORE
904 MULADDC_STOP
905 }
906#else
907 for( ; i >= 16; i -= 16 )
908 {
909 MULADDC_INIT
910 MULADDC_CORE MULADDC_CORE
911 MULADDC_CORE MULADDC_CORE
912 MULADDC_CORE MULADDC_CORE
913 MULADDC_CORE MULADDC_CORE
914
915 MULADDC_CORE MULADDC_CORE
916 MULADDC_CORE MULADDC_CORE
917 MULADDC_CORE MULADDC_CORE
918 MULADDC_CORE MULADDC_CORE
919 MULADDC_STOP
920 }
921
922 for( ; i >= 8; i -= 8 )
923 {
924 MULADDC_INIT
925 MULADDC_CORE MULADDC_CORE
926 MULADDC_CORE MULADDC_CORE
927
928 MULADDC_CORE MULADDC_CORE
929 MULADDC_CORE MULADDC_CORE
930 MULADDC_STOP
931 }
932
933 for( ; i > 0; i-- )
934 {
935 MULADDC_INIT
936 MULADDC_CORE
937 MULADDC_STOP
938 }
939#endif
940
941 t++;
942
943 do {
944 *d += c; c = ( *d < c ); d++;
945 }
946 while( c != 0 );
947}
948
949/*
950 * Baseline multiplication: X = A * B (HAC 14.12)
951 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000952int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +0000953{
954 int ret, i, j;
955 mpi TA, TB;
956
957 mpi_init( &TA, &TB, NULL );
958
959 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
960 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
961
962 for( i = A->n - 1; i >= 0; i-- )
963 if( A->p[i] != 0 )
964 break;
965
966 for( j = B->n - 1; j >= 0; j-- )
967 if( B->p[j] != 0 )
968 break;
969
970 MPI_CHK( mpi_grow( X, i + j + 2 ) );
971 MPI_CHK( mpi_lset( X, 0 ) );
972
973 for( i++; j >= 0; j-- )
974 mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
975
976 X->s = A->s * B->s;
977
978cleanup:
979
980 mpi_free( &TB, &TA, NULL );
981
982 return( ret );
983}
984
985/*
986 * Baseline multiplication: X = A * b
987 */
Paul Bakkerff60ee62010-03-16 21:09:09 +0000988int mpi_mul_int( mpi *X, const mpi *A, t_int b )
Paul Bakker5121ce52009-01-03 21:22:43 +0000989{
990 mpi _B;
991 t_int p[1];
992
993 _B.s = 1;
994 _B.n = 1;
995 _B.p = p;
996 p[0] = b;
997
998 return( mpi_mul_mpi( X, A, &_B ) );
999}
1000
1001/*
1002 * Division by mpi: A = Q * B + R (HAC 14.20)
1003 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001004int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001005{
1006 int ret, i, n, t, k;
1007 mpi X, Y, Z, T1, T2;
1008
1009 if( mpi_cmp_int( B, 0 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001010 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
1012 mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
1013
1014 if( mpi_cmp_abs( A, B ) < 0 )
1015 {
1016 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
1017 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
1018 return( 0 );
1019 }
1020
1021 MPI_CHK( mpi_copy( &X, A ) );
1022 MPI_CHK( mpi_copy( &Y, B ) );
1023 X.s = Y.s = 1;
1024
1025 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
1026 MPI_CHK( mpi_lset( &Z, 0 ) );
1027 MPI_CHK( mpi_grow( &T1, 2 ) );
1028 MPI_CHK( mpi_grow( &T2, 3 ) );
1029
1030 k = mpi_msb( &Y ) % biL;
1031 if( k < (int) biL - 1 )
1032 {
1033 k = biL - 1 - k;
1034 MPI_CHK( mpi_shift_l( &X, k ) );
1035 MPI_CHK( mpi_shift_l( &Y, k ) );
1036 }
1037 else k = 0;
1038
1039 n = X.n - 1;
1040 t = Y.n - 1;
1041 mpi_shift_l( &Y, biL * (n - t) );
1042
1043 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
1044 {
1045 Z.p[n - t]++;
1046 mpi_sub_mpi( &X, &X, &Y );
1047 }
1048 mpi_shift_r( &Y, biL * (n - t) );
1049
1050 for( i = n; i > t ; i-- )
1051 {
1052 if( X.p[i] >= Y.p[t] )
1053 Z.p[i - t - 1] = ~0;
1054 else
1055 {
Paul Bakker40e46942009-01-03 21:51:57 +00001056#if defined(POLARSSL_HAVE_LONGLONG)
Paul Bakker5121ce52009-01-03 21:22:43 +00001057 t_dbl r;
1058
1059 r = (t_dbl) X.p[i] << biL;
1060 r |= (t_dbl) X.p[i - 1];
1061 r /= Y.p[t];
1062 if( r > ((t_dbl) 1 << biL) - 1)
1063 r = ((t_dbl) 1 << biL) - 1;
1064
1065 Z.p[i - t - 1] = (t_int) r;
1066#else
1067 /*
1068 * __udiv_qrnnd_c, from gmp/longlong.h
1069 */
1070 t_int q0, q1, r0, r1;
1071 t_int d0, d1, d, m;
1072
1073 d = Y.p[t];
1074 d0 = ( d << biH ) >> biH;
1075 d1 = ( d >> biH );
1076
1077 q1 = X.p[i] / d1;
1078 r1 = X.p[i] - d1 * q1;
1079 r1 <<= biH;
1080 r1 |= ( X.p[i - 1] >> biH );
1081
1082 m = q1 * d0;
1083 if( r1 < m )
1084 {
1085 q1--, r1 += d;
1086 while( r1 >= d && r1 < m )
1087 q1--, r1 += d;
1088 }
1089 r1 -= m;
1090
1091 q0 = r1 / d1;
1092 r0 = r1 - d1 * q0;
1093 r0 <<= biH;
1094 r0 |= ( X.p[i - 1] << biH ) >> biH;
1095
1096 m = q0 * d0;
1097 if( r0 < m )
1098 {
1099 q0--, r0 += d;
1100 while( r0 >= d && r0 < m )
1101 q0--, r0 += d;
1102 }
1103 r0 -= m;
1104
1105 Z.p[i - t - 1] = ( q1 << biH ) | q0;
1106#endif
1107 }
1108
1109 Z.p[i - t - 1]++;
1110 do
1111 {
1112 Z.p[i - t - 1]--;
1113
1114 MPI_CHK( mpi_lset( &T1, 0 ) );
1115 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
1116 T1.p[1] = Y.p[t];
1117 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
1118
1119 MPI_CHK( mpi_lset( &T2, 0 ) );
1120 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
1121 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
1122 T2.p[2] = X.p[i];
1123 }
1124 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
1125
1126 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
1127 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1128 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
1129
1130 if( mpi_cmp_int( &X, 0 ) < 0 )
1131 {
1132 MPI_CHK( mpi_copy( &T1, &Y ) );
1133 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
1134 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
1135 Z.p[i - t - 1]--;
1136 }
1137 }
1138
1139 if( Q != NULL )
1140 {
1141 mpi_copy( Q, &Z );
1142 Q->s = A->s * B->s;
1143 }
1144
1145 if( R != NULL )
1146 {
1147 mpi_shift_r( &X, k );
1148 mpi_copy( R, &X );
1149
1150 R->s = A->s;
1151 if( mpi_cmp_int( R, 0 ) == 0 )
1152 R->s = 1;
1153 }
1154
1155cleanup:
1156
1157 mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
1158
1159 return( ret );
1160}
1161
1162/*
1163 * Division by int: A = Q * b + R
1164 *
1165 * Returns 0 if successful
1166 * 1 if memory allocation failed
Paul Bakker40e46942009-01-03 21:51:57 +00001167 * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
Paul Bakker5121ce52009-01-03 21:22:43 +00001168 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001169int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001170{
1171 mpi _B;
1172 t_int p[1];
1173
1174 p[0] = ( b < 0 ) ? -b : b;
1175 _B.s = ( b < 0 ) ? -1 : 1;
1176 _B.n = 1;
1177 _B.p = p;
1178
1179 return( mpi_div_mpi( Q, R, A, &_B ) );
1180}
1181
1182/*
1183 * Modulo: R = A mod B
1184 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001185int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001186{
1187 int ret;
1188
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001189 if( mpi_cmp_int( B, 0 ) < 0 )
1190 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
1191
Paul Bakker5121ce52009-01-03 21:22:43 +00001192 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
1193
1194 while( mpi_cmp_int( R, 0 ) < 0 )
1195 MPI_CHK( mpi_add_mpi( R, R, B ) );
1196
1197 while( mpi_cmp_mpi( R, B ) >= 0 )
1198 MPI_CHK( mpi_sub_mpi( R, R, B ) );
1199
1200cleanup:
1201
1202 return( ret );
1203}
1204
1205/*
1206 * Modulo: r = A mod b
1207 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001208int mpi_mod_int( t_int *r, const mpi *A, int b )
Paul Bakker5121ce52009-01-03 21:22:43 +00001209{
1210 int i;
1211 t_int x, y, z;
1212
1213 if( b == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001214 return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
Paul Bakker5121ce52009-01-03 21:22:43 +00001215
1216 if( b < 0 )
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001217 return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001218
1219 /*
1220 * handle trivial cases
1221 */
1222 if( b == 1 )
1223 {
1224 *r = 0;
1225 return( 0 );
1226 }
1227
1228 if( b == 2 )
1229 {
1230 *r = A->p[0] & 1;
1231 return( 0 );
1232 }
1233
1234 /*
1235 * general case
1236 */
1237 for( i = A->n - 1, y = 0; i >= 0; i-- )
1238 {
1239 x = A->p[i];
1240 y = ( y << biH ) | ( x >> biH );
1241 z = y / b;
1242 y -= z * b;
1243
1244 x <<= biH;
1245 y = ( y << biH ) | ( x >> biH );
1246 z = y / b;
1247 y -= z * b;
1248 }
1249
Paul Bakkerce40a6d2009-06-23 19:46:08 +00001250 /*
1251 * If A is negative, then the current y represents a negative value.
1252 * Flipping it to the positive side.
1253 */
1254 if( A->s < 0 && y != 0 )
1255 y = b - y;
1256
Paul Bakker5121ce52009-01-03 21:22:43 +00001257 *r = y;
1258
1259 return( 0 );
1260}
1261
1262/*
1263 * Fast Montgomery initialization (thanks to Tom St Denis)
1264 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001265static void mpi_montg_init( t_int *mm, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001266{
1267 t_int x, m0 = N->p[0];
1268
1269 x = m0;
1270 x += ( ( m0 + 2 ) & 4 ) << 1;
1271 x *= ( 2 - ( m0 * x ) );
1272
1273 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
1274 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
1275 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
1276
1277 *mm = ~x + 1;
1278}
1279
1280/*
1281 * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
1282 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001283static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_int mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001284{
1285 int i, n, m;
1286 t_int u0, u1, *d;
1287
1288 memset( T->p, 0, T->n * ciL );
1289
1290 d = T->p;
1291 n = N->n;
1292 m = ( B->n < n ) ? B->n : n;
1293
1294 for( i = 0; i < n; i++ )
1295 {
1296 /*
1297 * T = (T + u0*B + u1*N) / 2^biL
1298 */
1299 u0 = A->p[i];
1300 u1 = ( d[0] + u0 * B->p[0] ) * mm;
1301
1302 mpi_mul_hlp( m, B->p, d, u0 );
1303 mpi_mul_hlp( n, N->p, d, u1 );
1304
1305 *d++ = u0; d[n + 1] = 0;
1306 }
1307
1308 memcpy( A->p, d, (n + 1) * ciL );
1309
1310 if( mpi_cmp_abs( A, N ) >= 0 )
1311 mpi_sub_hlp( n, N->p, A->p );
1312 else
1313 /* prevent timing attacks */
1314 mpi_sub_hlp( n, A->p, T->p );
1315}
1316
1317/*
1318 * Montgomery reduction: A = A * R^-1 mod N
1319 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001320static void mpi_montred( mpi *A, const mpi *N, t_int mm, const mpi *T )
Paul Bakker5121ce52009-01-03 21:22:43 +00001321{
1322 t_int z = 1;
1323 mpi U;
1324
1325 U.n = U.s = z;
1326 U.p = &z;
1327
1328 mpi_montmul( A, &U, N, mm, T );
1329}
1330
1331/*
1332 * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
1333 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001334int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
Paul Bakker5121ce52009-01-03 21:22:43 +00001335{
1336 int ret, i, j, wsize, wbits;
1337 int bufsize, nblimbs, nbits;
1338 t_int ei, mm, state;
1339 mpi RR, T, W[64];
1340
1341 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001342 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001343
1344 /*
1345 * Init temps and window size
1346 */
1347 mpi_montg_init( &mm, N );
1348 mpi_init( &RR, &T, NULL );
1349 memset( W, 0, sizeof( W ) );
1350
1351 i = mpi_msb( E );
1352
1353 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
1354 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
1355
1356 j = N->n + 1;
1357 MPI_CHK( mpi_grow( X, j ) );
1358 MPI_CHK( mpi_grow( &W[1], j ) );
1359 MPI_CHK( mpi_grow( &T, j * 2 ) );
1360
1361 /*
1362 * If 1st call, pre-compute R^2 mod N
1363 */
1364 if( _RR == NULL || _RR->p == NULL )
1365 {
1366 MPI_CHK( mpi_lset( &RR, 1 ) );
1367 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
1368 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
1369
1370 if( _RR != NULL )
1371 memcpy( _RR, &RR, sizeof( mpi ) );
1372 }
1373 else
1374 memcpy( &RR, _RR, sizeof( mpi ) );
1375
1376 /*
1377 * W[1] = A * R^2 * R^-1 mod N = A * R mod N
1378 */
1379 if( mpi_cmp_mpi( A, N ) >= 0 )
1380 mpi_mod_mpi( &W[1], A, N );
1381 else mpi_copy( &W[1], A );
1382
1383 mpi_montmul( &W[1], &RR, N, mm, &T );
1384
1385 /*
1386 * X = R^2 * R^-1 mod N = R mod N
1387 */
1388 MPI_CHK( mpi_copy( X, &RR ) );
1389 mpi_montred( X, N, mm, &T );
1390
1391 if( wsize > 1 )
1392 {
1393 /*
1394 * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
1395 */
1396 j = 1 << (wsize - 1);
1397
1398 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
1399 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
1400
1401 for( i = 0; i < wsize - 1; i++ )
1402 mpi_montmul( &W[j], &W[j], N, mm, &T );
1403
1404 /*
1405 * W[i] = W[i - 1] * W[1]
1406 */
1407 for( i = j + 1; i < (1 << wsize); i++ )
1408 {
1409 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
1410 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
1411
1412 mpi_montmul( &W[i], &W[1], N, mm, &T );
1413 }
1414 }
1415
1416 nblimbs = E->n;
1417 bufsize = 0;
1418 nbits = 0;
1419 wbits = 0;
1420 state = 0;
1421
1422 while( 1 )
1423 {
1424 if( bufsize == 0 )
1425 {
1426 if( nblimbs-- == 0 )
1427 break;
1428
1429 bufsize = sizeof( t_int ) << 3;
1430 }
1431
1432 bufsize--;
1433
1434 ei = (E->p[nblimbs] >> bufsize) & 1;
1435
1436 /*
1437 * skip leading 0s
1438 */
1439 if( ei == 0 && state == 0 )
1440 continue;
1441
1442 if( ei == 0 && state == 1 )
1443 {
1444 /*
1445 * out of window, square X
1446 */
1447 mpi_montmul( X, X, N, mm, &T );
1448 continue;
1449 }
1450
1451 /*
1452 * add ei to current window
1453 */
1454 state = 2;
1455
1456 nbits++;
1457 wbits |= (ei << (wsize - nbits));
1458
1459 if( nbits == wsize )
1460 {
1461 /*
1462 * X = X^wsize R^-1 mod N
1463 */
1464 for( i = 0; i < wsize; i++ )
1465 mpi_montmul( X, X, N, mm, &T );
1466
1467 /*
1468 * X = X * W[wbits] R^-1 mod N
1469 */
1470 mpi_montmul( X, &W[wbits], N, mm, &T );
1471
1472 state--;
1473 nbits = 0;
1474 wbits = 0;
1475 }
1476 }
1477
1478 /*
1479 * process the remaining bits
1480 */
1481 for( i = 0; i < nbits; i++ )
1482 {
1483 mpi_montmul( X, X, N, mm, &T );
1484
1485 wbits <<= 1;
1486
1487 if( (wbits & (1 << wsize)) != 0 )
1488 mpi_montmul( X, &W[1], N, mm, &T );
1489 }
1490
1491 /*
1492 * X = A^E * R * R^-1 mod N = A^E mod N
1493 */
1494 mpi_montred( X, N, mm, &T );
1495
1496cleanup:
1497
1498 for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
1499 mpi_free( &W[i], NULL );
1500
1501 if( _RR != NULL )
1502 mpi_free( &W[1], &T, NULL );
1503 else mpi_free( &W[1], &T, &RR, NULL );
1504
1505 return( ret );
1506}
1507
Paul Bakker5121ce52009-01-03 21:22:43 +00001508/*
1509 * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
1510 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001511int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
Paul Bakker5121ce52009-01-03 21:22:43 +00001512{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001513 int ret, lz, lzt;
Paul Bakker5121ce52009-01-03 21:22:43 +00001514 mpi TG, TA, TB;
1515
1516 mpi_init( &TG, &TA, &TB, NULL );
1517
Paul Bakker5121ce52009-01-03 21:22:43 +00001518 MPI_CHK( mpi_copy( &TA, A ) );
1519 MPI_CHK( mpi_copy( &TB, B ) );
1520
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001521 lz = mpi_lsb( &TA );
1522 lzt = mpi_lsb( &TB );
1523
1524 if ( lzt < lz )
1525 lz = lzt;
1526
1527 MPI_CHK( mpi_shift_r( &TA, lz ) );
1528 MPI_CHK( mpi_shift_r( &TB, lz ) );
1529
Paul Bakker5121ce52009-01-03 21:22:43 +00001530 TA.s = TB.s = 1;
1531
1532 while( mpi_cmp_int( &TA, 0 ) != 0 )
1533 {
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001534 MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
1535 MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001536
1537 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
1538 {
1539 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
1540 MPI_CHK( mpi_shift_r( &TA, 1 ) );
1541 }
1542 else
1543 {
1544 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
1545 MPI_CHK( mpi_shift_r( &TB, 1 ) );
1546 }
1547 }
1548
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001549 MPI_CHK( mpi_shift_l( &TB, lz ) );
1550 MPI_CHK( mpi_copy( G, &TB ) );
Paul Bakker5121ce52009-01-03 21:22:43 +00001551
1552cleanup:
1553
1554 mpi_free( &TB, &TA, &TG, NULL );
1555
1556 return( ret );
1557}
1558
Paul Bakker70b3eed2009-03-14 18:01:25 +00001559#if defined(POLARSSL_GENPRIME)
1560
Paul Bakker5121ce52009-01-03 21:22:43 +00001561/*
1562 * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
1563 */
Paul Bakkerff60ee62010-03-16 21:09:09 +00001564int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
Paul Bakker5121ce52009-01-03 21:22:43 +00001565{
1566 int ret;
1567 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
1568
1569 if( mpi_cmp_int( N, 0 ) <= 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001570 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001571
1572 mpi_init( &TA, &TU, &U1, &U2, &G,
1573 &TB, &TV, &V1, &V2, NULL );
1574
1575 MPI_CHK( mpi_gcd( &G, A, N ) );
1576
1577 if( mpi_cmp_int( &G, 1 ) != 0 )
1578 {
Paul Bakker40e46942009-01-03 21:51:57 +00001579 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001580 goto cleanup;
1581 }
1582
1583 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
1584 MPI_CHK( mpi_copy( &TU, &TA ) );
1585 MPI_CHK( mpi_copy( &TB, N ) );
1586 MPI_CHK( mpi_copy( &TV, N ) );
1587
1588 MPI_CHK( mpi_lset( &U1, 1 ) );
1589 MPI_CHK( mpi_lset( &U2, 0 ) );
1590 MPI_CHK( mpi_lset( &V1, 0 ) );
1591 MPI_CHK( mpi_lset( &V2, 1 ) );
1592
1593 do
1594 {
1595 while( ( TU.p[0] & 1 ) == 0 )
1596 {
1597 MPI_CHK( mpi_shift_r( &TU, 1 ) );
1598
1599 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
1600 {
1601 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
1602 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
1603 }
1604
1605 MPI_CHK( mpi_shift_r( &U1, 1 ) );
1606 MPI_CHK( mpi_shift_r( &U2, 1 ) );
1607 }
1608
1609 while( ( TV.p[0] & 1 ) == 0 )
1610 {
1611 MPI_CHK( mpi_shift_r( &TV, 1 ) );
1612
1613 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
1614 {
1615 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
1616 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
1617 }
1618
1619 MPI_CHK( mpi_shift_r( &V1, 1 ) );
1620 MPI_CHK( mpi_shift_r( &V2, 1 ) );
1621 }
1622
1623 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
1624 {
1625 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
1626 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
1627 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
1628 }
1629 else
1630 {
1631 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
1632 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
1633 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
1634 }
1635 }
1636 while( mpi_cmp_int( &TU, 0 ) != 0 );
1637
1638 while( mpi_cmp_int( &V1, 0 ) < 0 )
1639 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
1640
1641 while( mpi_cmp_mpi( &V1, N ) >= 0 )
1642 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
1643
1644 MPI_CHK( mpi_copy( X, &V1 ) );
1645
1646cleanup:
1647
1648 mpi_free( &V2, &V1, &TV, &TB, &G,
1649 &U2, &U1, &TU, &TA, NULL );
1650
1651 return( ret );
1652}
1653
1654static const int small_prime[] =
1655{
1656 3, 5, 7, 11, 13, 17, 19, 23,
1657 29, 31, 37, 41, 43, 47, 53, 59,
1658 61, 67, 71, 73, 79, 83, 89, 97,
1659 101, 103, 107, 109, 113, 127, 131, 137,
1660 139, 149, 151, 157, 163, 167, 173, 179,
1661 181, 191, 193, 197, 199, 211, 223, 227,
1662 229, 233, 239, 241, 251, 257, 263, 269,
1663 271, 277, 281, 283, 293, 307, 311, 313,
1664 317, 331, 337, 347, 349, 353, 359, 367,
1665 373, 379, 383, 389, 397, 401, 409, 419,
1666 421, 431, 433, 439, 443, 449, 457, 461,
1667 463, 467, 479, 487, 491, 499, 503, 509,
1668 521, 523, 541, 547, 557, 563, 569, 571,
1669 577, 587, 593, 599, 601, 607, 613, 617,
1670 619, 631, 641, 643, 647, 653, 659, 661,
1671 673, 677, 683, 691, 701, 709, 719, 727,
1672 733, 739, 743, 751, 757, 761, 769, 773,
1673 787, 797, 809, 811, 821, 823, 827, 829,
1674 839, 853, 857, 859, 863, 877, 881, 883,
1675 887, 907, 911, 919, 929, 937, 941, 947,
1676 953, 967, 971, 977, 983, 991, 997, -103
1677};
1678
1679/*
1680 * Miller-Rabin primality test (HAC 4.24)
1681 */
1682int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
1683{
1684 int ret, i, j, n, s, xs;
1685 mpi W, R, T, A, RR;
1686 unsigned char *p;
1687
Paul Bakker48eab262009-06-25 21:25:49 +00001688 if( mpi_cmp_int( X, 0 ) == 0 ||
1689 mpi_cmp_int( X, 1 ) == 0 )
1690 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
1691
1692 if( mpi_cmp_int( X, 2 ) == 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +00001693 return( 0 );
1694
1695 mpi_init( &W, &R, &T, &A, &RR, NULL );
1696
1697 xs = X->s; X->s = 1;
1698
1699 /*
1700 * test trivial factors first
1701 */
1702 if( ( X->p[0] & 1 ) == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001703 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001704
1705 for( i = 0; small_prime[i] > 0; i++ )
1706 {
1707 t_int r;
1708
1709 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
1710 return( 0 );
1711
1712 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
1713
1714 if( r == 0 )
Paul Bakker40e46942009-01-03 21:51:57 +00001715 return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
Paul Bakker5121ce52009-01-03 21:22:43 +00001716 }
1717
1718 /*
1719 * W = |X| - 1
1720 * R = W >> lsb( W )
1721 */
Paul Bakker5121ce52009-01-03 21:22:43 +00001722 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
Paul Bakker41d13f42010-03-16 21:26:36 +00001723 s = mpi_lsb( &W );
Paul Bakker5121ce52009-01-03 21:22:43 +00001724 MPI_CHK( mpi_copy( &R, &W ) );
1725 MPI_CHK( mpi_shift_r( &R, s ) );
1726
1727 i = mpi_msb( X );
1728 /*
1729 * HAC, table 4.4
1730 */
1731 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
1732 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
1733 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
1734
1735 for( i = 0; i < n; i++ )
1736 {
1737 /*
1738 * pick a random A, 1 < A < |X| - 1
1739 */
1740 MPI_CHK( mpi_grow( &A, X->n ) );
1741
1742 p = (unsigned char *) A.p;
1743 for( j = 0; j < A.n * ciL; j++ )
1744 *p++ = (unsigned char) f_rng( p_rng );
1745
1746 j = mpi_msb( &A ) - mpi_msb( &W );
1747 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
1748 A.p[0] |= 3;
1749
1750 /*
1751 * A = A^R mod |X|
1752 */
1753 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
1754
1755 if( mpi_cmp_mpi( &A, &W ) == 0 ||
1756 mpi_cmp_int( &A, 1 ) == 0 )
1757 continue;
1758
1759 j = 1;
1760 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
1761 {
1762 /*
1763 * A = A * A mod |X|
1764 */
1765 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
1766 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
1767
1768 if( mpi_cmp_int( &A, 1 ) == 0 )
1769 break;
1770
1771 j++;
1772 }
1773
1774 /*
1775 * not prime if A != |X| - 1 or A == 1
1776 */
1777 if( mpi_cmp_mpi( &A, &W ) != 0 ||
1778 mpi_cmp_int( &A, 1 ) == 0 )
1779 {
Paul Bakker40e46942009-01-03 21:51:57 +00001780 ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
Paul Bakker5121ce52009-01-03 21:22:43 +00001781 break;
1782 }
1783 }
1784
1785cleanup:
1786
1787 X->s = xs;
1788
1789 mpi_free( &RR, &A, &T, &R, &W, NULL );
1790
1791 return( ret );
1792}
1793
1794/*
1795 * Prime number generation
1796 */
1797int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
1798 int (*f_rng)(void *), void *p_rng )
1799{
1800 int ret, k, n;
1801 unsigned char *p;
1802 mpi Y;
1803
1804 if( nbits < 3 )
Paul Bakker40e46942009-01-03 21:51:57 +00001805 return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +00001806
1807 mpi_init( &Y, NULL );
1808
1809 n = BITS_TO_LIMBS( nbits );
1810
1811 MPI_CHK( mpi_grow( X, n ) );
1812 MPI_CHK( mpi_lset( X, 0 ) );
1813
1814 p = (unsigned char *) X->p;
1815 for( k = 0; k < X->n * ciL; k++ )
1816 *p++ = (unsigned char) f_rng( p_rng );
1817
1818 k = mpi_msb( X );
1819 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
1820 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
1821
1822 X->p[0] |= 3;
1823
1824 if( dh_flag == 0 )
1825 {
1826 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
1827 {
Paul Bakker40e46942009-01-03 21:51:57 +00001828 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001829 goto cleanup;
1830
1831 MPI_CHK( mpi_add_int( X, X, 2 ) );
1832 }
1833 }
1834 else
1835 {
1836 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
1837 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1838
1839 while( 1 )
1840 {
1841 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
1842 {
1843 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
1844 break;
1845
Paul Bakker40e46942009-01-03 21:51:57 +00001846 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001847 goto cleanup;
1848 }
1849
Paul Bakker40e46942009-01-03 21:51:57 +00001850 if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
Paul Bakker5121ce52009-01-03 21:22:43 +00001851 goto cleanup;
1852
1853 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
1854 MPI_CHK( mpi_add_int( X, X, 2 ) );
1855 MPI_CHK( mpi_shift_r( &Y, 1 ) );
1856 }
1857 }
1858
1859cleanup:
1860
1861 mpi_free( &Y, NULL );
1862
1863 return( ret );
1864}
1865
1866#endif
1867
Paul Bakker40e46942009-01-03 21:51:57 +00001868#if defined(POLARSSL_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +00001869
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001870#define GCD_PAIR_COUNT 3
1871
1872static const int gcd_pairs[GCD_PAIR_COUNT][3] =
1873{
1874 { 693, 609, 21 },
1875 { 1764, 868, 28 },
1876 { 768454923, 542167814, 1 }
1877};
1878
Paul Bakker5121ce52009-01-03 21:22:43 +00001879/*
1880 * Checkup routine
1881 */
1882int mpi_self_test( int verbose )
1883{
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001884 int ret, i;
Paul Bakker5121ce52009-01-03 21:22:43 +00001885 mpi A, E, N, X, Y, U, V;
1886
1887 mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
1888
1889 MPI_CHK( mpi_read_string( &A, 16,
1890 "EFE021C2645FD1DC586E69184AF4A31E" \
1891 "D5F53E93B5F123FA41680867BA110131" \
1892 "944FE7952E2517337780CB0DB80E61AA" \
1893 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
1894
1895 MPI_CHK( mpi_read_string( &E, 16,
1896 "B2E7EFD37075B9F03FF989C7C5051C20" \
1897 "34D2A323810251127E7BF8625A4F49A5" \
1898 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
1899 "5B5C25763222FEFCCFC38B832366C29E" ) );
1900
1901 MPI_CHK( mpi_read_string( &N, 16,
1902 "0066A198186C18C10B2F5ED9B522752A" \
1903 "9830B69916E535C8F047518A889A43A5" \
1904 "94B6BED27A168D31D4A52F88925AA8F5" ) );
1905
1906 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
1907
1908 MPI_CHK( mpi_read_string( &U, 16,
1909 "602AB7ECA597A3D6B56FF9829A5E8B85" \
1910 "9E857EA95A03512E2BAE7391688D264A" \
1911 "A5663B0341DB9CCFD2C4C5F421FEC814" \
1912 "8001B72E848A38CAE1C65F78E56ABDEF" \
1913 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
1914 "ECF677152EF804370C1A305CAF3B5BF1" \
1915 "30879B56C61DE584A0F53A2447A51E" ) );
1916
1917 if( verbose != 0 )
1918 printf( " MPI test #1 (mul_mpi): " );
1919
1920 if( mpi_cmp_mpi( &X, &U ) != 0 )
1921 {
1922 if( verbose != 0 )
1923 printf( "failed\n" );
1924
1925 return( 1 );
1926 }
1927
1928 if( verbose != 0 )
1929 printf( "passed\n" );
1930
1931 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
1932
1933 MPI_CHK( mpi_read_string( &U, 16,
1934 "256567336059E52CAE22925474705F39A94" ) );
1935
1936 MPI_CHK( mpi_read_string( &V, 16,
1937 "6613F26162223DF488E9CD48CC132C7A" \
1938 "0AC93C701B001B092E4E5B9F73BCD27B" \
1939 "9EE50D0657C77F374E903CDFA4C642" ) );
1940
1941 if( verbose != 0 )
1942 printf( " MPI test #2 (div_mpi): " );
1943
1944 if( mpi_cmp_mpi( &X, &U ) != 0 ||
1945 mpi_cmp_mpi( &Y, &V ) != 0 )
1946 {
1947 if( verbose != 0 )
1948 printf( "failed\n" );
1949
1950 return( 1 );
1951 }
1952
1953 if( verbose != 0 )
1954 printf( "passed\n" );
1955
1956 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
1957
1958 MPI_CHK( mpi_read_string( &U, 16,
1959 "36E139AEA55215609D2816998ED020BB" \
1960 "BD96C37890F65171D948E9BC7CBAA4D9" \
1961 "325D24D6A3C12710F10A09FA08AB87" ) );
1962
1963 if( verbose != 0 )
1964 printf( " MPI test #3 (exp_mod): " );
1965
1966 if( mpi_cmp_mpi( &X, &U ) != 0 )
1967 {
1968 if( verbose != 0 )
1969 printf( "failed\n" );
1970
1971 return( 1 );
1972 }
1973
1974 if( verbose != 0 )
1975 printf( "passed\n" );
1976
1977 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
1978
1979 MPI_CHK( mpi_read_string( &U, 16,
1980 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
1981 "C3DBA76456363A10869622EAC2DD84EC" \
1982 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
1983
1984 if( verbose != 0 )
1985 printf( " MPI test #4 (inv_mod): " );
1986
1987 if( mpi_cmp_mpi( &X, &U ) != 0 )
1988 {
1989 if( verbose != 0 )
1990 printf( "failed\n" );
1991
1992 return( 1 );
1993 }
1994
1995 if( verbose != 0 )
1996 printf( "passed\n" );
1997
Paul Bakker4e0d7ca2009-01-29 22:24:33 +00001998 if( verbose != 0 )
1999 printf( " MPI test #5 (simple gcd): " );
2000
2001 for ( i = 0; i < GCD_PAIR_COUNT; i++)
2002 {
2003 MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
2004 MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
2005
2006 MPI_CHK( mpi_gcd( &A, &X, &Y ) );
2007
2008 if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
2009 {
2010 if( verbose != 0 )
2011 printf( "failed at %d\n", i );
2012
2013 return( 1 );
2014 }
2015 }
2016
2017 if( verbose != 0 )
2018 printf( "passed\n" );
2019
Paul Bakker5121ce52009-01-03 21:22:43 +00002020cleanup:
2021
2022 if( ret != 0 && verbose != 0 )
2023 printf( "Unexpected error, return code = %08X\n", ret );
2024
2025 mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
2026
2027 if( verbose != 0 )
2028 printf( "\n" );
2029
2030 return( ret );
2031}
2032
2033#endif
2034
2035#endif