00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _CRT_SECURE_NO_DEPRECATE
00031 #define _CRT_SECURE_NO_DEPRECATE 1
00032 #endif
00033
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <stdarg.h>
00037 #include <stdio.h>
00038
00039 #include "xyssl/bignum.h"
00040 #include "xyssl/bn_asm.h"
00041
00042
00043
00044
00045 #define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
00046 #define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
00047
00048
00049
00050
00051 void mpi_init( mpi *X, ... )
00052 {
00053 va_list args;
00054
00055 va_start( args, X );
00056
00057 while( X != NULL )
00058 {
00059 memset( X, 0, sizeof( mpi ) );
00060 X = va_arg( args, mpi* );
00061 }
00062
00063 va_end( args );
00064 }
00065
00066
00067
00068
00069 void mpi_free( mpi *X, ... )
00070 {
00071 va_list args;
00072
00073 va_start( args, X );
00074
00075 while( X != NULL )
00076 {
00077 if( X->p != NULL )
00078 {
00079 memset( X->p, 0, X->n * ciL );
00080 free( X->p );
00081 }
00082
00083 memset( X, 0, sizeof( mpi ) );
00084
00085 X = va_arg( args, mpi* );
00086 }
00087
00088 va_end( args );
00089 }
00090
00091
00092
00093
00094 int mpi_grow( mpi *X, int nblimbs )
00095 {
00096 int n = X->n;
00097
00098 if( n < nblimbs )
00099 {
00100 if( X->s == 0 )
00101 X->s = 1;
00102
00103 X->n = nblimbs;
00104 X->p = (t_int *) realloc( X->p, X->n * ciL );
00105
00106 if( X->p == NULL )
00107 return( 1 );
00108
00109 memset( X->p + n, 0, ( X->n - n ) * ciL );
00110 }
00111
00112 return( 0 );
00113 }
00114
00115
00116
00117
00118 int mpi_copy( mpi *X, mpi *Y )
00119 {
00120 int ret, i;
00121
00122 if( X == Y )
00123 return( 0 );
00124
00125 for( i = Y->n - 1; i > 0; i-- )
00126 if( Y->p[i] != 0 )
00127 break;
00128 i++;
00129
00130 X->s = Y->s;
00131
00132 CHK( mpi_grow( X, i ) );
00133
00134 memset( X->p, 0, X->n * ciL );
00135 memcpy( X->p, Y->p, i * ciL );
00136
00137 cleanup:
00138
00139 return( ret );
00140 }
00141
00142
00143
00144
00145 void mpi_swap( mpi *X, mpi *Y )
00146 {
00147 mpi T;
00148
00149 memcpy( &T, X , sizeof( mpi ) );
00150 memcpy( X , Y , sizeof( mpi ) );
00151 memcpy( Y , &T, sizeof( mpi ) );
00152 }
00153
00154
00155
00156
00157 int mpi_lset( mpi *X, int z )
00158 {
00159 int ret;
00160
00161 CHK( mpi_grow( X, 1 ) );
00162 memset( X->p, 0, X->n * ciL );
00163 X->p[0] = ( z < 0 ) ? -z : z;
00164 X->s = ( z < 0 ) ? -1 : 1;
00165
00166 cleanup:
00167
00168 return( ret );
00169 }
00170
00171
00172
00173
00174 static int mpi_get_digit( t_int *d, int radix, char c )
00175 {
00176 *d = 16;
00177
00178 if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
00179 if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
00180 if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
00181
00182 if( *d >= (t_int) radix )
00183 return( ERR_MPI_INVALID_CHARACTER );
00184
00185 return( 0 );
00186 }
00187
00188
00189
00190
00191 int mpi_read_string( mpi *X, int radix, char *s )
00192 {
00193 int ret, i, j, n;
00194 t_int d;
00195 mpi T;
00196
00197 if( radix < 2 || radix > 16 )
00198 return( ERR_MPI_INVALID_PARAMETER );
00199
00200 mpi_init( &T, NULL );
00201
00202 if( radix == 16 )
00203 {
00204 n = BITS_TO_LIMBS( strlen( s ) << 2 );
00205
00206 CHK( mpi_grow( X, n ) );
00207 CHK( mpi_lset( X, 0 ) );
00208
00209 for( i = strlen( s ) - 1, j = 0; i >= 0; i--, j++ )
00210 {
00211 if( i == 0 && s[i] == '-' )
00212 {
00213 X->s = -1;
00214 break;
00215 }
00216
00217 CHK( mpi_get_digit( &d, radix, s[i] ) );
00218 X->p[j / (ciL * 2)] |= d << ( (j % (ciL * 2)) << 2 );
00219 }
00220 }
00221 else
00222 {
00223 CHK( mpi_lset( X, 0 ) );
00224
00225 for( i = 0; i < (int) strlen( s ); i++ )
00226 {
00227 if( i == 0 && s[i] == '-' )
00228 {
00229 X->s = -1;
00230 continue;
00231 }
00232
00233 CHK( mpi_get_digit( &d, radix, s[i] ) );
00234 CHK( mpi_mul_int( &T, X, radix ) );
00235 CHK( mpi_add_int( X, &T, d ) );
00236 }
00237 }
00238
00239 cleanup:
00240
00241 mpi_free( &T, NULL );
00242 return( ret );
00243 }
00244
00245
00246
00247
00248 static int mpi_write_hlp( mpi *X, int radix, char **p )
00249 {
00250 int ret;
00251 t_int r;
00252
00253 if( radix < 2 || radix > 16 )
00254 return( ERR_MPI_INVALID_PARAMETER );
00255
00256 CHK( mpi_mod_int( &r, X, radix ) );
00257 CHK( mpi_div_int( X, NULL, X, radix ) );
00258
00259 if( mpi_cmp_int( X, 0 ) != 0 )
00260 CHK( mpi_write_hlp( X, radix, p ) );
00261
00262 *(*p)++ = ( r < 10 ) ? ( (char) r + 0x30 )
00263 : ( (char) r + 0x37 );
00264
00265 cleanup:
00266
00267 return( ret );
00268 }
00269
00270
00271
00272
00273 int mpi_write_string( mpi *X, int radix, char *s, int *slen )
00274 {
00275 int ret = 0, n;
00276 char *p;
00277 mpi T;
00278
00279 if( radix < 2 || radix > 16 )
00280 return( ERR_MPI_INVALID_PARAMETER );
00281
00282 n = mpi_msb( X );
00283 if( radix >= 4 ) n >>= 1;
00284 if( radix >= 16 ) n >>= 1;
00285 n += 3;
00286
00287 if( *slen < n )
00288 {
00289 *slen = n;
00290 return( ERR_MPI_BUFFER_TOO_SMALL );
00291 }
00292
00293 p = s;
00294 mpi_init( &T, NULL );
00295
00296 if( X->s == -1 )
00297 *p++ = '-';
00298
00299 if( radix == 16 )
00300 {
00301 int c, i, j, k;
00302
00303 for( i = X->n - 1, k = 0; i >= 0; i-- )
00304 {
00305 for( j = ciL - 1; j >= 0; j-- )
00306 {
00307 c = ( X->p[i] >> (j << 3) ) & 0xFF;
00308
00309 if( c == 0 && k == 0 && (i + j) != 0 )
00310 continue;
00311
00312 p += sprintf( p, "%02X", c );
00313 k = 1;
00314 }
00315 }
00316 }
00317 else
00318 {
00319 CHK( mpi_copy( &T, X ) );
00320 CHK( mpi_write_hlp( &T, radix, &p ) );
00321 }
00322
00323 *p++ = '\0';
00324 *slen = p - s;
00325
00326 cleanup:
00327
00328 mpi_free( &T, NULL );
00329 return( ret );
00330 }
00331
00332
00333
00334
00335 int mpi_read_file( mpi *X, int radix, FILE *fin )
00336 {
00337 char s[1536], *p;
00338 int slen;
00339 t_int d;
00340
00341 memset( s, 0, sizeof( s ) );
00342 if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
00343 return( ERR_MPI_FILE_IO_ERROR );
00344
00345 slen = strlen( s );
00346 if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
00347 if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
00348
00349 p = s + slen;
00350 while( --p >= s )
00351 if( mpi_get_digit( &d, radix, *p ) != 0 )
00352 break;
00353
00354 return( mpi_read_string( X, radix, p + 1 ) );
00355 }
00356
00357
00358
00359
00360 int mpi_write_file( char *p, mpi *X, int radix, FILE *fout )
00361 {
00362 int ret = 0;
00363 size_t slen;
00364 size_t plen;
00365 char s[1536];
00366
00367 slen = sizeof( s );
00368 memset( s, 0, slen );
00369 slen -= 2;
00370
00371 CHK( mpi_write_string( X, radix, s, (int *) &slen ) );
00372
00373 if( p == NULL )
00374 p = "";
00375
00376 plen = strlen( p );
00377 slen = strlen( s );
00378 s[slen++] = '\r';
00379 s[slen++] = '\n';
00380
00381 if( fout != NULL )
00382 {
00383 if( fwrite( p, 1, plen, fout ) != plen ||
00384 fwrite( s, 1, slen, fout ) != slen )
00385 return( ERR_MPI_FILE_IO_ERROR );
00386 }
00387 else
00388 printf( "%s%s", p, s );
00389
00390 cleanup:
00391
00392 return( ret );
00393 }
00394
00395
00396
00397
00398 int mpi_read_binary( mpi *X, unsigned char *buf, int buflen )
00399 {
00400 int ret, i, j, n;
00401
00402 for( n = 0; n < buflen; n++ )
00403 if( buf[n] != 0 )
00404 break;
00405
00406 CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
00407 CHK( mpi_lset( X, 0 ) );
00408
00409 for( i = buflen - 1, j = 0; i >= n; i--, j++ )
00410 X->p[j / ciL] |= (t_int)( buf[i] << ((j % ciL) << 3) );
00411
00412 cleanup:
00413
00414 return( ret );
00415 }
00416
00417
00418
00419
00420 int mpi_write_binary( mpi *X, unsigned char *buf, int *buflen )
00421 {
00422 int i, j, n;
00423
00424 n = ( mpi_msb( X ) + 7 ) >> 3;
00425
00426 if( *buflen < n )
00427 {
00428 *buflen = n;
00429 return( ERR_MPI_BUFFER_TOO_SMALL );
00430 }
00431
00432 memset( buf, 0, *buflen );
00433
00434 for( i = *buflen - 1, j = 0; n > 0; i--, j++, n-- )
00435 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
00436
00437 return( 0 );
00438 }
00439
00440
00441
00442
00443 int mpi_msb( mpi *X )
00444 {
00445 int i, j;
00446
00447 for( i = X->n - 1; i > 0; i-- )
00448 if( X->p[i] != 0 )
00449 break;
00450
00451 for( j = biL - 1; j >= 0; j-- )
00452 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
00453 break;
00454
00455 return( ( i * biL ) + j + 1 );
00456 }
00457
00458
00459
00460
00461 int mpi_lsb( mpi *X )
00462 {
00463 int i, j, count = 0;
00464
00465 for( i = 0; i < X->n; i++ )
00466 for( j = 0; j < (int) biL; j++, count++ )
00467 if( ( ( X->p[i] >> j ) & 1 ) != 0 )
00468 return( count );
00469
00470 return( 0 );
00471 }
00472
00473
00474
00475
00476 int mpi_shift_l( mpi *X, int count )
00477 {
00478 int ret, i, v0, t1;
00479 t_int r0 = 0, r1;
00480
00481 v0 = count / biL;
00482 t1 = count & (biL - 1);
00483
00484 i = mpi_msb( X ) + count;
00485
00486 if( X->n * (int) biL < i )
00487 CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
00488
00489 ret = 0;
00490
00491
00492
00493
00494 if( v0 > 0 )
00495 {
00496 for( i = X->n - 1; i >= v0; i-- )
00497 X->p[i] = X->p[i - v0];
00498
00499 for( ; i >= 0; i-- )
00500 X->p[i] = 0;
00501 }
00502
00503
00504
00505
00506 if( t1 > 0 )
00507 {
00508 for( i = v0; i < X->n; i++ )
00509 {
00510 r1 = X->p[i] >> (biL - t1);
00511 X->p[i] <<= t1;
00512 X->p[i] |= r0;
00513 r0 = r1;
00514 }
00515 }
00516
00517 cleanup:
00518
00519 return( ret );
00520 }
00521
00522
00523
00524
00525 int mpi_shift_r( mpi *X, int count )
00526 {
00527 int i, v0, v1;
00528 t_int r0 = 0, r1;
00529
00530 v0 = count / biL;
00531 v1 = count & (biL - 1);
00532
00533
00534
00535
00536 if( v0 > 0 )
00537 {
00538 for( i = 0; i < X->n - v0; i++ )
00539 X->p[i] = X->p[i + v0];
00540
00541 for( ; i < X->n; i++ )
00542 X->p[i] = 0;
00543 }
00544
00545
00546
00547
00548 if( v1 > 0 )
00549 {
00550 for( i = X->n - 1; i >= 0; i-- )
00551 {
00552 r1 = X->p[i] << (biL - v1);
00553 X->p[i] >>= v1;
00554 X->p[i] |= r0;
00555 r0 = r1;
00556 }
00557 }
00558
00559 return( 0 );
00560 }
00561
00562
00563
00564
00565 int mpi_cmp_abs( mpi *X, mpi *Y )
00566 {
00567 int i, j;
00568
00569 for( i = X->n - 1; i >= 0; i-- )
00570 if( X->p[i] != 0 )
00571 break;
00572
00573 for( j = Y->n - 1; j >= 0; j-- )
00574 if( Y->p[j] != 0 )
00575 break;
00576
00577 if( i < 0 && j < 0 )
00578 return( 0 );
00579
00580 if( i > j ) return( 1 );
00581 if( j > i ) return( -1 );
00582
00583 for( ; i >= 0; i-- )
00584 {
00585 if( X->p[i] > Y->p[i] ) return( 1 );
00586 if( X->p[i] < Y->p[i] ) return( -1 );
00587 }
00588
00589 return( 0 );
00590 }
00591
00592
00593
00594
00595 int mpi_cmp_mpi( mpi *X, mpi *Y )
00596 {
00597 int i, j;
00598
00599 for( i = X->n - 1; i >= 0; i-- )
00600 if( X->p[i] != 0 )
00601 break;
00602
00603 for( j = Y->n - 1; j >= 0; j-- )
00604 if( Y->p[j] != 0 )
00605 break;
00606
00607 if( i < 0 && j < 0 )
00608 return( 0 );
00609
00610 if( i > j ) return( X->s );
00611 if( j > i ) return( -X->s );
00612
00613 if( X->s > 0 && Y->s < 0 ) return( 1 );
00614 if( Y->s > 0 && X->s < 0 ) return( -1 );
00615
00616 for( ; i >= 0; i-- )
00617 {
00618 if( X->p[i] > Y->p[i] ) return( X->s );
00619 if( X->p[i] < Y->p[i] ) return( -X->s );
00620 }
00621
00622 return( 0 );
00623 }
00624
00625
00626
00627
00628 int mpi_cmp_int( mpi *X, int z )
00629 {
00630 mpi Y;
00631 t_int p[1];
00632
00633 *p = ( z < 0 ) ? -z : z;
00634 Y.s = ( z < 0 ) ? -1 : 1;
00635 Y.n = 1;
00636 Y.p = p;
00637
00638 return( mpi_cmp_mpi( X, &Y ) );
00639 }
00640
00641
00642
00643
00644 int mpi_add_abs( mpi *X, mpi *A, mpi *B )
00645 {
00646 int ret, i, j;
00647 t_int *o, *p, c;
00648
00649 if( X == B )
00650 {
00651 mpi *T = A; A = X; B = T;
00652 }
00653
00654 if( X != A )
00655 CHK( mpi_copy( X, A ) );
00656
00657 for( j = B->n - 1; j >= 0; j-- )
00658 if( B->p[j] != 0 )
00659 break;
00660
00661 CHK( mpi_grow( X, j + 1 ) );
00662
00663 o = B->p; p = X->p; c = 0;
00664
00665 for( i = 0; i <= j; i++, o++, p++ )
00666 {
00667 *p += c; c = ( *p < c );
00668 *p += *o; c += ( *p < *o );
00669 }
00670
00671 while( c != 0 )
00672 {
00673 if( i >= X->n )
00674 {
00675 CHK( mpi_grow( X, i + 1 ) );
00676 p = X->p + i;
00677 }
00678
00679 *p += c; c = ( *p < c ); i++;
00680 }
00681
00682 cleanup:
00683
00684 return( ret );
00685 }
00686
00687
00688
00689
00690 static void mpi_sub_hlp( int n, t_int *s, t_int *d )
00691 {
00692 int i;
00693 t_int c, z;
00694
00695 for( i = c = 0; i < n; i++, s++, d++ )
00696 {
00697 z = ( *d < c ); *d -= c;
00698 c = ( *d < *s ) + z; *d -= *s;
00699 }
00700
00701 while( c != 0 )
00702 {
00703 z = ( *d < c ); *d -= c;
00704 c = z; i++; d++;
00705 }
00706 }
00707
00708
00709
00710
00711 int mpi_sub_abs( mpi *X, mpi *A, mpi *B )
00712 {
00713 mpi TB;
00714 int ret, n;
00715
00716 if( mpi_cmp_abs( A, B ) < 0 )
00717 return( ERR_MPI_NEGATIVE_VALUE );
00718
00719 mpi_init( &TB, NULL );
00720
00721 if( X == B )
00722 {
00723 CHK( mpi_copy( &TB, B ) );
00724 B = &TB;
00725 }
00726
00727 if( X != A )
00728 CHK( mpi_copy( X, A ) );
00729
00730 ret = 0;
00731
00732 for( n = B->n - 1; n >= 0; n-- )
00733 if( B->p[n] != 0 )
00734 break;
00735
00736 mpi_sub_hlp( n + 1, B->p, X->p );
00737
00738 cleanup:
00739
00740 mpi_free( &TB, NULL );
00741 return( ret );
00742 }
00743
00744
00745
00746
00747 int mpi_add_mpi( mpi *X, mpi *A, mpi *B )
00748 {
00749 int ret, s = A->s;
00750
00751 if( A->s * B->s < 0 )
00752 {
00753 if( mpi_cmp_abs( A, B ) >= 0 )
00754 {
00755 CHK( mpi_sub_abs( X, A, B ) );
00756 X->s = s;
00757 }
00758 else
00759 {
00760 CHK( mpi_sub_abs( X, B, A ) );
00761 X->s = -s;
00762 }
00763 }
00764 else
00765 {
00766 CHK( mpi_add_abs( X, A, B ) );
00767 X->s = s;
00768 }
00769
00770 cleanup:
00771
00772 return( ret );
00773 }
00774
00775
00776
00777
00778 int mpi_sub_mpi( mpi *X, mpi *A, mpi *B )
00779 {
00780 int ret, s = A->s;
00781
00782 if( A->s * B->s > 0 )
00783 {
00784 if( mpi_cmp_abs( A, B ) >= 0 )
00785 {
00786 CHK( mpi_sub_abs( X, A, B ) );
00787 X->s = s;
00788 }
00789 else
00790 {
00791 CHK( mpi_sub_abs( X, B, A ) );
00792 X->s = -s;
00793 }
00794 }
00795 else
00796 {
00797 CHK( mpi_add_abs( X, A, B ) );
00798 X->s = s;
00799 }
00800
00801 cleanup:
00802
00803 return( ret );
00804 }
00805
00806
00807
00808
00809 int mpi_add_int( mpi *X, mpi *A, int b )
00810 {
00811 mpi _B;
00812 t_int p[1];
00813
00814 p[0] = ( b < 0 ) ? -b : b;
00815 _B.s = ( b < 0 ) ? -1 : 1;
00816 _B.n = 1;
00817 _B.p = p;
00818
00819 return( mpi_add_mpi( X, A, &_B ) );
00820 }
00821
00822
00823
00824
00825 int mpi_sub_int( mpi *X, mpi *A, int b )
00826 {
00827 mpi _B;
00828 t_int p[1];
00829
00830 p[0] = ( b < 0 ) ? -b : b;
00831 _B.s = ( b < 0 ) ? -1 : 1;
00832 _B.n = 1;
00833 _B.p = p;
00834
00835 return( mpi_sub_mpi( X, A, &_B ) );
00836 }
00837
00838
00839
00840
00841 static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
00842 {
00843 t_int c = 0, t = 0;
00844
00845 #if defined(MULADDC_HUIT)
00846 for( ; i >= 8; i -= 8 )
00847 {
00848 MULADDC_INIT
00849 MULADDC_HUIT
00850 MULADDC_STOP
00851 }
00852
00853 for( ; i > 0; i-- )
00854 {
00855 MULADDC_INIT
00856 MULADDC_CORE
00857 MULADDC_STOP
00858 }
00859 #else
00860 for( ; i >= 16; i -= 16 )
00861 {
00862 MULADDC_INIT
00863 MULADDC_CORE MULADDC_CORE
00864 MULADDC_CORE MULADDC_CORE
00865 MULADDC_CORE MULADDC_CORE
00866 MULADDC_CORE MULADDC_CORE
00867
00868 MULADDC_CORE MULADDC_CORE
00869 MULADDC_CORE MULADDC_CORE
00870 MULADDC_CORE MULADDC_CORE
00871 MULADDC_CORE MULADDC_CORE
00872 MULADDC_STOP
00873 }
00874
00875 for( ; i >= 8; i -= 8 )
00876 {
00877 MULADDC_INIT
00878 MULADDC_CORE MULADDC_CORE
00879 MULADDC_CORE MULADDC_CORE
00880
00881 MULADDC_CORE MULADDC_CORE
00882 MULADDC_CORE MULADDC_CORE
00883 MULADDC_STOP
00884 }
00885
00886 for( ; i > 0; i-- )
00887 {
00888 MULADDC_INIT
00889 MULADDC_CORE
00890 MULADDC_STOP
00891 }
00892 #endif
00893
00894 t++;
00895
00896 do {
00897 *d += c; c = ( *d < c ); d++;
00898 }
00899 while( c != 0 );
00900 }
00901
00902
00903
00904
00905 int mpi_mul_mpi( mpi *X, mpi *A, mpi *B )
00906 {
00907 int ret, i, j;
00908 mpi TA, TB;
00909
00910 mpi_init( &TA, &TB, NULL );
00911
00912 if( X == A ) { CHK( mpi_copy( &TA, A ) ); A = &TA; }
00913 if( X == B ) { CHK( mpi_copy( &TB, B ) ); B = &TB; }
00914
00915 for( i = A->n - 1; i >= 0; i-- )
00916 if( A->p[i] != 0 )
00917 break;
00918
00919 for( j = B->n - 1; j >= 0; j-- )
00920 if( B->p[j] != 0 )
00921 break;
00922
00923 CHK( mpi_grow( X, i + j + 2 ) );
00924 CHK( mpi_lset( X, 0 ) );
00925
00926 for( i++; j >= 0; j-- )
00927 mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
00928
00929 X->s = A->s * B->s;
00930
00931 cleanup:
00932
00933 mpi_free( &TB, &TA, NULL );
00934 return( ret );
00935 }
00936
00937
00938
00939
00940 int mpi_mul_int( mpi *X, mpi *A, t_int b )
00941 {
00942 mpi _B;
00943 t_int p[1];
00944
00945 _B.s = 1;
00946 _B.n = 1;
00947 _B.p = p;
00948 p[0] = b;
00949
00950 return( mpi_mul_mpi( X, A, &_B ) );
00951 }
00952
00953
00954
00955
00956 int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B )
00957 {
00958 int ret, i, n, t, k;
00959 mpi X, Y, Z, T1, T2;
00960
00961 if( mpi_cmp_int( B, 0 ) == 0 )
00962 return( ERR_MPI_DIVISION_BY_ZERO );
00963
00964 mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
00965
00966 if( mpi_cmp_abs( A, B ) < 0 )
00967 {
00968 if( Q != NULL ) CHK( mpi_lset( Q, 0 ) );
00969 if( R != NULL ) CHK( mpi_copy( R, A ) );
00970 return( 0 );
00971 }
00972
00973 CHK( mpi_copy( &X, A ) );
00974 CHK( mpi_copy( &Y, B ) );
00975 X.s = Y.s = 1;
00976
00977 CHK( mpi_grow( &Z, A->n + 2 ) );
00978 CHK( mpi_lset( &Z, 0 ) );
00979 CHK( mpi_grow( &T1, 2 ) );
00980 CHK( mpi_grow( &T2, 3 ) );
00981
00982 k = mpi_msb( &Y ) % biL;
00983 if( k < (int) biL - 1 )
00984 {
00985 k = biL - 1 - k;
00986 CHK( mpi_shift_l( &X, k ) );
00987 CHK( mpi_shift_l( &Y, k ) );
00988 }
00989 else k = 0;
00990
00991 n = X.n - 1;
00992 t = Y.n - 1;
00993 mpi_shift_l( &Y, biL * (n - t) );
00994
00995 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
00996 {
00997 Z.p[n - t]++;
00998 mpi_sub_mpi( &X, &X, &Y );
00999 }
01000 mpi_shift_r( &Y, biL * (n - t) );
01001
01002 for( i = n; i > t ; i-- )
01003 {
01004 if( X.p[i] >= Y.p[t] )
01005 Z.p[i - t - 1] = ~0;
01006 else
01007 {
01008 #if defined(HAVE_LONGLONG)
01009 t_dbl r;
01010
01011 r = (t_dbl) X.p[i] << biL;
01012 r |= (t_dbl) X.p[i - 1];
01013 r /= Y.p[t];
01014 if( r > ((t_dbl) 1 << biL) - 1)
01015 r = ((t_dbl) 1 << biL) - 1;
01016
01017 Z.p[i - t - 1] = (t_int) r;
01018 #else
01019
01020
01021
01022 t_int q0, q1, r0, r1;
01023 t_int d0, d1, d, m;
01024
01025 d = Y.p[t];
01026 d0 = ( d << biH ) >> biH;
01027 d1 = ( d >> biH );
01028
01029 q1 = X.p[i] / d1;
01030 r1 = X.p[i] - d1 * q1;
01031 r1 <<= biH;
01032 r1 |= ( X.p[i - 1] >> biH );
01033
01034 m = q1 * d0;
01035 if( r1 < m )
01036 {
01037 q1--, r1 += d;
01038 while( r1 >= d && r1 < m )
01039 q1--, r1 += d;
01040 }
01041 r1 -= m;
01042
01043 q0 = r1 / d1;
01044 r0 = r1 - d1 * q0;
01045 r0 <<= biH;
01046 r0 |= ( X.p[i - 1] << biH ) >> biH;
01047
01048 m = q0 * d0;
01049 if( r0 < m )
01050 {
01051 q0--, r0 += d;
01052 while( r0 >= d && r0 < m )
01053 q0--, r0 += d;
01054 }
01055 r0 -= m;
01056
01057 Z.p[i - t - 1] = ( q1 << biH ) | q0;
01058 #endif
01059 }
01060
01061 Z.p[i - t - 1]++;
01062 do
01063 {
01064 Z.p[i - t - 1]--;
01065
01066 CHK( mpi_lset( &T1, 0 ) );
01067 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
01068 T1.p[1] = Y.p[t];
01069 CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
01070
01071 CHK( mpi_lset( &T2, 0 ) );
01072 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
01073 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
01074 T2.p[2] = X.p[i];
01075 }
01076 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
01077
01078 CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
01079 CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
01080 CHK( mpi_sub_mpi( &X, &X, &T1 ) );
01081
01082 if( mpi_cmp_int( &X, 0 ) < 0 )
01083 {
01084 CHK( mpi_copy( &T1, &Y ) );
01085 CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
01086 CHK( mpi_add_mpi( &X, &X, &T1 ) );
01087 Z.p[i - t - 1]--;
01088 }
01089 }
01090
01091 if( Q != NULL )
01092 {
01093 mpi_copy( Q, &Z );
01094 Q->s = A->s * B->s;
01095 }
01096
01097 if( R != NULL )
01098 {
01099 mpi_shift_r( &X, k );
01100 mpi_copy( R, &X );
01101
01102 R->s = A->s;
01103 if( mpi_cmp_int( R, 0 ) == 0 )
01104 R->s = 1;
01105 }
01106
01107 cleanup:
01108
01109 mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
01110 return( ret );
01111 }
01112
01113
01114
01115
01116
01117
01118
01119
01120 int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b )
01121 {
01122 mpi _B;
01123 t_int p[1];
01124
01125 p[0] = ( b < 0 ) ? -b : b;
01126 _B.s = ( b < 0 ) ? -1 : 1;
01127 _B.n = 1;
01128 _B.p = p;
01129
01130 return( mpi_div_mpi( Q, R, A, &_B ) );
01131 }
01132
01133
01134
01135
01136 int mpi_mod_mpi( mpi *R, mpi *A, mpi *B )
01137 {
01138 int ret;
01139
01140 CHK( mpi_div_mpi( NULL, R, A, B ) );
01141
01142 while( mpi_cmp_int( R, 0 ) < 0 )
01143 CHK( mpi_add_mpi( R, R, B ) );
01144
01145 while( mpi_cmp_mpi( R, B ) >= 0 )
01146 CHK( mpi_sub_mpi( R, R, B ) );
01147
01148 cleanup:
01149
01150 return( ret );
01151 }
01152
01153
01154
01155
01156 int mpi_mod_int( t_int *r, mpi *A, int b )
01157 {
01158 int i;
01159 t_int x, y, z;
01160
01161 if( b == 0 )
01162 return( ERR_MPI_DIVISION_BY_ZERO );
01163
01164 if( b < 0 )
01165 b = -b;
01166
01167
01168
01169
01170 if( b == 1 ) { *r = 0; return( 0 ); }
01171 if( b == 2 ) { *r = A->p[0] & 1; return( 0 ); }
01172
01173
01174
01175
01176 for( i = A->n - 1, y = 0; i >= 0; i-- )
01177 {
01178 x = A->p[i];
01179 y = ( y << biH ) | ( x >> biH );
01180 z = y / b;
01181 y -= z * b;
01182
01183 x <<= biH;
01184 y = ( y << biH ) | ( x >> biH );
01185 z = y / b;
01186 y -= z * b;
01187 }
01188
01189 *r = y;
01190
01191 return( 0 );
01192 }
01193
01194
01195
01196
01197 static void mpi_montg_init( t_int *mm, mpi *N )
01198 {
01199 t_int x, m0 = N->p[0];
01200
01201 x = m0;
01202 x += ((m0 + 2) & 4) << 1;
01203 x *= (2 - (m0 * x));
01204
01205 if( biL >= 16 ) x *= (2 - (m0 * x));
01206 if( biL >= 32 ) x *= (2 - (m0 * x));
01207 if( biL >= 64 ) x *= (2 - (m0 * x));
01208
01209 *mm = ~x + 1;
01210 }
01211
01212
01213
01214
01215 static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T )
01216 {
01217 int i, n, m;
01218 t_int u0, u1, *d;
01219
01220 memset( T->p, 0, ciL * T->n );
01221
01222 d = T->p;
01223 n = N->n;
01224 m = ( B->n < n ) ? B->n : n;
01225
01226 for( i = 0; i < n; i++ )
01227 {
01228
01229
01230
01231 u0 = A->p[i];
01232 u1 = ( d[0] + u0 * B->p[0] ) * mm;
01233
01234 mpi_mul_hlp( m, B->p, d, u0 );
01235 mpi_mul_hlp( n, N->p, d, u1 );
01236
01237 *d++ = u0; d[n + 1] = 0;
01238 }
01239
01240 memcpy( A->p, d, ciL * (n + 1) );
01241
01242 if( mpi_cmp_abs( A, N ) >= 0 )
01243 mpi_sub_hlp( n, N->p, A->p );
01244 else
01245
01246 mpi_sub_hlp( n, A->p, T->p );
01247 }
01248
01249
01250
01251
01252 static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T )
01253 {
01254 t_int z = 1;
01255 mpi U;
01256
01257 U.n = U.s = z;
01258 U.p = &z;
01259
01260 mpi_montmul( A, &U, N, mm, T );
01261 }
01262
01263
01264
01265
01266 int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR )
01267 {
01268 int ret, i, j, wsize, wbits;
01269 int bufsize, nblimbs, nbits;
01270 t_int ei, mm, state;
01271 mpi RR, T, W[64];
01272
01273 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
01274 return( ERR_MPI_INVALID_PARAMETER );
01275
01276
01277
01278
01279 mpi_montg_init( &mm, N );
01280 mpi_init( &RR, &T, NULL );
01281 memset( W, 0, sizeof( W ) );
01282
01283 i = mpi_msb( E );
01284
01285 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
01286 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
01287
01288 j = N->n + 1;
01289 CHK( mpi_grow( X, j ) );
01290 CHK( mpi_grow( &W[1], j ) );
01291 CHK( mpi_grow( &T, j * 2 ) );
01292
01293
01294
01295
01296 if( _RR == NULL || _RR->p == NULL )
01297 {
01298 CHK( mpi_lset( &RR, 1 ) );
01299 CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
01300 CHK( mpi_mod_mpi( &RR, &RR, N ) );
01301
01302 if( _RR != NULL )
01303 memcpy( _RR, &RR, sizeof( mpi ) );
01304 }
01305 else
01306 memcpy( &RR, _RR, sizeof( mpi ) );
01307
01308
01309
01310
01311 if( mpi_cmp_mpi( A, N ) >= 0 )
01312 mpi_mod_mpi( &W[1], A, N );
01313 else mpi_copy( &W[1], A );
01314
01315 mpi_montmul( &W[1], &RR, N, mm, &T );
01316
01317
01318
01319
01320 CHK( mpi_copy( X, &RR ) );
01321 mpi_montred( X, N, mm, &T );
01322
01323 if( wsize > 1 )
01324 {
01325
01326
01327
01328 j = 1 << (wsize - 1);
01329
01330 CHK( mpi_grow( &W[j], N->n + 1 ) );
01331 CHK( mpi_copy( &W[j], &W[1] ) );
01332
01333 for( i = 0; i < wsize - 1; i++ )
01334 mpi_montmul( &W[j], &W[j], N, mm, &T );
01335
01336
01337
01338
01339 for( i = j + 1; i < (1 << wsize); i++ )
01340 {
01341 CHK( mpi_grow( &W[i], N->n + 1 ) );
01342 CHK( mpi_copy( &W[i], &W[i - 1] ) );
01343
01344 mpi_montmul( &W[i], &W[1], N, mm, &T );
01345 }
01346 }
01347
01348 nblimbs = E->n;
01349 bufsize = 0;
01350 nbits = 0;
01351 wbits = 0;
01352 state = 0;
01353
01354 while( 1 )
01355 {
01356 if( bufsize == 0 )
01357 {
01358 if( nblimbs-- == 0 )
01359 break;
01360
01361 bufsize = sizeof( t_int ) << 3;
01362 }
01363
01364 bufsize--;
01365
01366 ei = (E->p[nblimbs] >> bufsize) & 1;
01367
01368
01369
01370
01371 if( ei == 0 && state == 0 )
01372 continue;
01373
01374 if( ei == 0 && state == 1 )
01375 {
01376
01377
01378
01379 mpi_montmul( X, X, N, mm, &T );
01380 continue;
01381 }
01382
01383
01384
01385
01386 state = 2;
01387
01388 nbits++;
01389 wbits |= (ei << (wsize - nbits));
01390
01391 if( nbits == wsize )
01392 {
01393
01394
01395
01396 for( i = 0; i < wsize; i++ )
01397 mpi_montmul( X, X, N, mm, &T );
01398
01399
01400
01401
01402 mpi_montmul( X, &W[wbits], N, mm, &T );
01403
01404 state--;
01405 nbits = 0;
01406 wbits = 0;
01407 }
01408 }
01409
01410
01411
01412
01413 for( i = 0; i < nbits; i++ )
01414 {
01415 mpi_montmul( X, X, N, mm, &T );
01416
01417 wbits <<= 1;
01418
01419 if( (wbits & (1 << wsize)) != 0 )
01420 mpi_montmul( X, &W[1], N, mm, &T );
01421 }
01422
01423
01424
01425
01426 mpi_montred( X, N, mm, &T );
01427
01428 cleanup:
01429
01430 for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
01431 mpi_free( &W[i], NULL );
01432
01433 if( _RR != NULL )
01434 mpi_free( &W[1], &T, NULL );
01435 else mpi_free( &W[1], &T, &RR, NULL );
01436
01437 return( ret );
01438 }
01439
01440
01441
01442
01443 int mpi_gcd( mpi *G, mpi *A, mpi *B )
01444 {
01445 int ret, count;
01446 mpi TG, TA, TB;
01447
01448 mpi_init( &TG, &TA, &TB, NULL );
01449
01450 CHK( mpi_lset( &TG, 1 ) );
01451 CHK( mpi_copy( &TA, A ) );
01452 CHK( mpi_copy( &TB, B ) );
01453
01454 TA.s = TB.s = 1;
01455
01456 count = ( mpi_lsb( &TA ) < mpi_lsb( &TB ) )
01457 ? mpi_lsb( &TA ) : mpi_lsb( &TB );
01458
01459 CHK( mpi_shift_l( &TG, count ) );
01460 CHK( mpi_shift_r( &TA, count ) );
01461 CHK( mpi_shift_r( &TB, count ) );
01462
01463 while( mpi_cmp_int( &TA, 0 ) != 0 )
01464 {
01465 while( ( TA.p[0] & 1 ) == 0 ) CHK( mpi_shift_r( &TA, 1 ) );
01466 while( ( TB.p[0] & 1 ) == 0 ) CHK( mpi_shift_r( &TB, 1 ) );
01467
01468 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
01469 {
01470 CHK( mpi_sub_abs( &TA, &TA, &TB ) );
01471 CHK( mpi_shift_r( &TA, 1 ) );
01472 }
01473 else
01474 {
01475 CHK( mpi_sub_abs( &TB, &TB, &TA ) );
01476 CHK( mpi_shift_r( &TB, 1 ) );
01477 }
01478 }
01479
01480 CHK( mpi_mul_mpi( G, &TG, &TB ) );
01481
01482 cleanup:
01483
01484 mpi_free( &TB, &TA, &TG, NULL );
01485 return( ret );
01486 }
01487
01488
01489
01490
01491 int mpi_inv_mod( mpi *X, mpi *A, mpi *N )
01492 {
01493 int ret;
01494 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
01495
01496 if( mpi_cmp_int( N, 0 ) <= 0 )
01497 return( ERR_MPI_INVALID_PARAMETER );
01498
01499 mpi_init( &TA, &TU, &U1, &U2, &G,
01500 &TB, &TV, &V1, &V2, NULL );
01501
01502 CHK( mpi_gcd( &G, A, N ) );
01503
01504 if( mpi_cmp_int( &G, 1 ) != 0 )
01505 {
01506 ret = ERR_MPI_NOT_ACCEPTABLE;
01507 goto cleanup;
01508 }
01509
01510 CHK( mpi_mod_mpi( &TA, A, N ) );
01511 CHK( mpi_copy( &TU, &TA ) );
01512 CHK( mpi_copy( &TB, N ) );
01513 CHK( mpi_copy( &TV, N ) );
01514
01515 CHK( mpi_lset( &U1, 1 ) );
01516 CHK( mpi_lset( &U2, 0 ) );
01517 CHK( mpi_lset( &V1, 0 ) );
01518 CHK( mpi_lset( &V2, 1 ) );
01519
01520 do
01521 {
01522 while( ( TU.p[0] & 1 ) == 0 )
01523 {
01524 CHK( mpi_shift_r( &TU, 1 ) );
01525
01526 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
01527 {
01528 CHK( mpi_add_mpi( &U1, &U1, &TB ) );
01529 CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
01530 }
01531
01532 CHK( mpi_shift_r( &U1, 1 ) );
01533 CHK( mpi_shift_r( &U2, 1 ) );
01534 }
01535
01536 while( ( TV.p[0] & 1 ) == 0 )
01537 {
01538 CHK( mpi_shift_r( &TV, 1 ) );
01539
01540 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
01541 {
01542 CHK( mpi_add_mpi( &V1, &V1, &TB ) );
01543 CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
01544 }
01545
01546 CHK( mpi_shift_r( &V1, 1 ) );
01547 CHK( mpi_shift_r( &V2, 1 ) );
01548 }
01549
01550 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
01551 {
01552 CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
01553 CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
01554 CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
01555 }
01556 else
01557 {
01558 CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
01559 CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
01560 CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
01561 }
01562 }
01563 while( mpi_cmp_int( &TU, 0 ) != 0 );
01564
01565 while( mpi_cmp_int( &V1, 0 ) < 0 )
01566 CHK( mpi_add_mpi( &V1, &V1, N ) );
01567
01568 while( mpi_cmp_mpi( &V1, N ) >= 0 )
01569 CHK( mpi_sub_mpi( &V1, &V1, N ) );
01570
01571 CHK( mpi_copy( X, &V1 ) );
01572
01573 cleanup:
01574
01575 mpi_free( &V2, &V1, &TV, &TB, &G,
01576 &U2, &U1, &TU, &TA, NULL );
01577
01578 return( ret );
01579 }
01580
01581 #if !defined(NO_GENPRIME)
01582 static const int small_prime[] =
01583 {
01584 3, 113, 271, 443, 619, 821, 1013, 1213,
01585 5, 127, 277, 449, 631, 823, 1019, 1217,
01586 7, 131, 281, 457, 641, 827, 1021, 1223,
01587 11, 137, 283, 461, 643, 829, 1031, 1229,
01588 13, 139, 293, 463, 647, 839, 1033, 1231,
01589 17, 149, 307, 467, 653, 853, 1039, 1237,
01590 19, 151, 311, 479, 659, 857, 1049, 1249,
01591 23, 157, 313, 487, 661, 859, 1051, 1259,
01592 29, 163, 317, 491, 673, 863, 1061, 1277,
01593 31, 167, 331, 499, 677, 877, 1063, 1279,
01594 37, 173, 337, 503, 683, 881, 1069, 1283,
01595 41, 179, 347, 509, 691, 883, 1087, 1289,
01596 43, 181, 349, 521, 701, 887, 1091, 1291,
01597 47, 191, 353, 523, 709, 907, 1093, 1297,
01598 53, 193, 359, 541, 719, 911, 1097, 1301,
01599 59, 197, 367, 547, 727, 919, 1103, 1303,
01600 61, 199, 373, 557, 733, 929, 1109, 1307,
01601 67, 211, 379, 563, 739, 937, 1117, 1319,
01602 71, 223, 383, 569, 743, 941, 1123, 1321,
01603 73, 227, 389, 571, 751, 947, 1129, 1327,
01604 79, 229, 397, 577, 757, 953, 1151, 1361,
01605 83, 233, 401, 587, 761, 967, 1153, 1367,
01606 89, 239, 409, 593, 769, 971, 1163, 1373,
01607 97, 241, 419, 599, 773, 977, 1171, 1381,
01608 101, 251, 421, 601, 787, 983, 1181, 1399,
01609 103, 257, 431, 607, 797, 991, 1187, 1409,
01610 107, 263, 433, 613, 809, 997, 1193, 1423,
01611 109, 269, 439, 617, 811, 1009, 1201, -111
01612 };
01613
01614
01615
01616
01617 int mpi_is_prime( mpi *X )
01618 {
01619 int ret, i, j, s, xs;
01620 mpi W, R, T, A, RR;
01621
01622 if( mpi_cmp_int( X, 0 ) == 0 )
01623 return( 0 );
01624
01625 mpi_init( &W, &R, &T, &A, &RR, NULL );
01626 xs = X->s; X->s = 1;
01627
01628
01629
01630
01631 if( ( X->p[0] & 1 ) == 0 )
01632 return( ERR_MPI_NOT_ACCEPTABLE );
01633
01634 for( i = 0; small_prime[i] > 0; i++ )
01635 {
01636 t_int r;
01637
01638 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
01639 return( 0 );
01640
01641 CHK( mpi_mod_int( &r, X, small_prime[i] ) );
01642
01643 if( r == 0 )
01644 return( ERR_MPI_NOT_ACCEPTABLE );
01645 }
01646
01647
01648
01649
01650
01651 CHK( mpi_sub_int( &W, X, 1 ) );
01652 CHK( mpi_copy( &R, &W ) );
01653 CHK( mpi_shift_r( &R, s = mpi_lsb( &W ) ) );
01654
01655 for( i = 0; i < 8; i++ )
01656 {
01657
01658
01659
01660 CHK( mpi_grow( &A, X->n ) );
01661
01662 for( j = 0; j < A.n; j++ )
01663 A.p[j] = (t_int) rand() * rand();
01664
01665 CHK( mpi_shift_r( &A, mpi_msb( &A ) -
01666 mpi_msb( &W ) + 1 ) );
01667 A.p[0] |= 3;
01668
01669
01670
01671
01672 CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
01673
01674 if( mpi_cmp_mpi( &A, &W ) == 0 ||
01675 mpi_cmp_int( &A, 1 ) == 0 )
01676 continue;
01677
01678 j = 1;
01679 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
01680 {
01681
01682
01683
01684 CHK( mpi_mul_mpi( &T, &A, &A ) );
01685 CHK( mpi_mod_mpi( &A, &T, X ) );
01686
01687 if( mpi_cmp_int( &A, 1 ) == 0 )
01688 break;
01689
01690 j++;
01691 }
01692
01693
01694
01695
01696 if( mpi_cmp_mpi( &A, &W ) != 0 || j < s )
01697 {
01698 ret = ERR_MPI_NOT_ACCEPTABLE;
01699 break;
01700 }
01701 }
01702
01703 cleanup:
01704
01705 X->s = xs;
01706 mpi_free( &A, &T, &R, &W, NULL );
01707 return( ret );
01708 }
01709
01710
01711
01712
01713 int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
01714 int (*rng_f)(void *), void *rng_d )
01715 {
01716 int ret, k, n;
01717 unsigned char *p;
01718 mpi Y;
01719
01720 if( nbits < 3 )
01721 return( ERR_MPI_INVALID_PARAMETER );
01722
01723 mpi_init( &Y, NULL );
01724
01725 n = BITS_TO_LIMBS( nbits );
01726
01727 CHK( mpi_grow( X, n ) );
01728 CHK( mpi_lset( X, 0 ) );
01729
01730 p = (unsigned char *) X->p;
01731 for( k = 0; k < ciL * X->n; k++ )
01732 *p++ = rng_f( rng_d );
01733
01734 k = mpi_msb( X );
01735 if( k < nbits ) CHK( mpi_shift_l( X, nbits - k ) );
01736 if( k > nbits ) CHK( mpi_shift_r( X, k - nbits ) );
01737 X->p[0] |= 3;
01738
01739 if( dh_flag == 0 )
01740 {
01741 while( ( ret = mpi_is_prime( X ) ) != 0 )
01742 {
01743 if( ret != ERR_MPI_NOT_ACCEPTABLE )
01744 goto cleanup;
01745
01746 CHK( mpi_add_int( X, X, 2 ) );
01747 }
01748 }
01749 else
01750 {
01751 CHK( mpi_sub_int( &Y, X, 1 ) );
01752 CHK( mpi_shift_r( &Y, 1 ) );
01753
01754 while( 1 )
01755 {
01756 if( ( ret = mpi_is_prime( X ) ) == 0 )
01757 {
01758 if( ( ret = mpi_is_prime( &Y ) ) == 0 )
01759 break;
01760
01761 if( ret != ERR_MPI_NOT_ACCEPTABLE )
01762 goto cleanup;
01763 }
01764
01765 if( ret != ERR_MPI_NOT_ACCEPTABLE )
01766 goto cleanup;
01767
01768 CHK( mpi_add_int( &Y, X, 1 ) );
01769 CHK( mpi_add_int( X, X, 2 ) );
01770 CHK( mpi_shift_r( &Y, 1 ) );
01771 }
01772 }
01773
01774 cleanup:
01775
01776 mpi_free( &Y, NULL );
01777 return( ret );
01778 }
01779 #endif
01780
01781 static const char _bignum_src[] = "_bignum_src";
01782
01783 #if defined(SELF_TEST)
01784
01785
01786
01787 int mpi_self_test( int verbose )
01788 {
01789 int ret;
01790 mpi A, E, N, X, Y, U, V;
01791
01792 mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
01793
01794 CHK( mpi_read_string( &A, 16,
01795 "EFE021C2645FD1DC586E69184AF4A31E" \
01796 "D5F53E93B5F123FA41680867BA110131" \
01797 "944FE7952E2517337780CB0DB80E61AA" \
01798 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
01799
01800 CHK( mpi_read_string( &E, 16,
01801 "B2E7EFD37075B9F03FF989C7C5051C20" \
01802 "34D2A323810251127E7BF8625A4F49A5" \
01803 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
01804 "5B5C25763222FEFCCFC38B832366C29E" ) );
01805
01806 CHK( mpi_read_string( &N, 16,
01807 "0066A198186C18C10B2F5ED9B522752A" \
01808 "9830B69916E535C8F047518A889A43A5" \
01809 "94B6BED27A168D31D4A52F88925AA8F5" ) );
01810
01811 CHK( mpi_mul_mpi( &X, &A, &N ) );
01812
01813 CHK( mpi_read_string( &U, 16,
01814 "602AB7ECA597A3D6B56FF9829A5E8B85" \
01815 "9E857EA95A03512E2BAE7391688D264A" \
01816 "A5663B0341DB9CCFD2C4C5F421FEC814" \
01817 "8001B72E848A38CAE1C65F78E56ABDEF" \
01818 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
01819 "ECF677152EF804370C1A305CAF3B5BF1" \
01820 "30879B56C61DE584A0F53A2447A51E" ) );
01821
01822 if( verbose != 0 )
01823 printf( " MPI test #1 (mul_mpi): " );
01824
01825 if( mpi_cmp_mpi( &X, &U ) != 0 )
01826 {
01827 if( verbose != 0 )
01828 printf( "failed\n" );
01829
01830 return( 1 );
01831 }
01832
01833 if( verbose != 0 )
01834 printf( "passed\n" );
01835
01836 CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
01837
01838 CHK( mpi_read_string( &U, 16,
01839 "256567336059E52CAE22925474705F39A94" ) );
01840
01841 CHK( mpi_read_string( &V, 16,
01842 "6613F26162223DF488E9CD48CC132C7A" \
01843 "0AC93C701B001B092E4E5B9F73BCD27B" \
01844 "9EE50D0657C77F374E903CDFA4C642" ) );
01845
01846 if( verbose != 0 )
01847 printf( " MPI test #2 (div_mpi): " );
01848
01849 if( mpi_cmp_mpi( &X, &U ) != 0 ||
01850 mpi_cmp_mpi( &Y, &V ) != 0 )
01851 {
01852 if( verbose != 0 )
01853 printf( "failed\n" );
01854
01855 return( 1 );
01856 }
01857
01858 if( verbose != 0 )
01859 printf( "passed\n" );
01860
01861 CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
01862
01863 CHK( mpi_read_string( &U, 16,
01864 "36E139AEA55215609D2816998ED020BB" \
01865 "BD96C37890F65171D948E9BC7CBAA4D9" \
01866 "325D24D6A3C12710F10A09FA08AB87" ) );
01867
01868 if( verbose != 0 )
01869 printf( " MPI test #3 (exp_mod): " );
01870
01871 if( mpi_cmp_mpi( &X, &U ) != 0 )
01872 {
01873 if( verbose != 0 )
01874 printf( "failed\n" );
01875
01876 return( 1 );
01877 }
01878
01879 if( verbose != 0 )
01880 printf( "passed\n" );
01881
01882 CHK( mpi_inv_mod( &X, &A, &N ) );
01883
01884 CHK( mpi_read_string( &U, 16,
01885 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
01886 "C3DBA76456363A10869622EAC2DD84EC" \
01887 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
01888
01889 if( verbose != 0 )
01890 printf( " MPI test #4 (inv_mod): " );
01891
01892 if( mpi_cmp_mpi( &X, &U ) != 0 )
01893 {
01894 if( verbose != 0 )
01895 printf( "failed\n" );
01896
01897 return( 1 );
01898 }
01899
01900 if( verbose != 0 )
01901 printf( "passed\n" );
01902
01903 cleanup:
01904
01905 if( ret != 0 && verbose != 0 )
01906 printf( "Unexpected error, return code = %08X\n", ret );
01907
01908 mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
01909
01910 if( verbose != 0 )
01911 printf( "\n" );
01912
01913 return( ret );
01914 }
01915 #else
01916 int mpi_self_test( int verbose )
01917 {
01918 return( 0 );
01919 }
01920 #endif