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