/home/dko/projects/mobilec/trunk/src/security/xyssl-0.9/library/bignum.c

Go to the documentation of this file.
00001 /*
00002  * Multi-precision integer library
00003  *
00004  * Copyright (C) 2006-2007 Christophe Devine
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00019  */
00020 /*
00021  * This MPI implementation is based on:
00022  *
00023  * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
00024  * http://www.stillhq.com/extracted/gnupg-api/mpi/
00025  * http://math.libtomcrypt.com/files/tommath.pdf
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)) /* chars in limb */
00040 #define biL (ciL << 3) /* bits in limb */
00041 #define biH (ciL << 2) /* half limb size */
00042 
00043 /*
00044  * Convert between bits/chars and number of limbs
00045  */
00046 #define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL)
00047 #define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
00048 
00049 /*
00050  * Initialize one or more mpi
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  * Unallocate one or more mpi
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  * Enlarge to the specified number of limbs
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  * Copy the contents of Y into X
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  * Swap the contents of X and Y
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  * Set value from integer
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  * Return the number of least significant bits
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  * Return the number of most significant bits
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  * Return the total size in bytes
00217  */
00218 int mpi_size( mpi *X )
00219 {
00220 return( ( mpi_msb( X ) + 7 ) >> 3 );
00221 }
00222 
00223 /*
00224  * Convert an ASCII character to digit value
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  * Import from an ASCII string
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  * Helper to write the digits high-order first
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  * Export into an ASCII string
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  * Read X from an opened file
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  * Write X into an opened file (or stdout if fout == NULL)
00416  */
00417 int mpi_write_file( char *p, mpi *X, int radix, FILE *fout )
00418 {
00419 int n, ret;
00420 size_t slen;
00421 size_t plen;
00422 char s[1024];
00423 
00424 n = sizeof( s );
00425 memset( s, 0, n );
00426 n -= 2;
00427 
00428 MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );
00429 
00430 if( p == NULL ) p = "";
00431 
00432 plen = strlen( p );
00433 slen = strlen( s );
00434 s[slen++] = '\r';
00435 s[slen++] = '\n';
00436 
00437 if( fout != NULL )
00438 {
00439 if( fwrite( p, 1, plen, fout ) != plen ||
00440 fwrite( s, 1, slen, fout ) != slen )
00441 return( XYSSL_ERR_MPI_FILE_IO_ERROR );
00442 }
00443 else
00444 printf( "%s%s", p, s );
00445 
00446 cleanup:
00447 
00448 return( ret );
00449 }
00450 
00451 /*
00452  * Import X from unsigned binary data, big endian
00453  */
00454 int mpi_read_binary( mpi *X, unsigned char *buf, int buflen )
00455 {
00456 int ret, i, j, n;
00457 
00458 for( n = 0; n < buflen; n++ )
00459 if( buf[n] != 0 )
00460 break;
00461 
00462 MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
00463 MPI_CHK( mpi_lset( X, 0 ) );
00464 
00465 for( i = buflen - 1, j = 0; i >= n; i--, j++ )
00466 X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);
00467 
00468 cleanup:
00469 
00470 return( ret );
00471 }
00472 
00473 /*
00474  * Export X into unsigned binary data, big endian
00475  */
00476 int mpi_write_binary( mpi *X, unsigned char *buf, int buflen )
00477 {
00478 int i, j, n;
00479 
00480 n = mpi_size( X );
00481 
00482 if( buflen < n )
00483 return( XYSSL_ERR_MPI_BUFFER_TOO_SMALL );
00484 
00485 memset( buf, 0, buflen );
00486 
00487 for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
00488 buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
00489 
00490 return( 0 );
00491 }
00492 
00493 /*
00494  * Left-shift: X <<= count
00495  */
00496 int mpi_shift_l( mpi *X, int count )
00497 {
00498 int ret, i, v0, t1;
00499 t_int r0 = 0, r1;
00500 
00501 v0 = count / (biL );
00502 t1 = count & (biL - 1);
00503 
00504 i = mpi_msb( X ) + count;
00505 
00506 if( X->n * (int) biL < i )
00507 MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
00508 
00509 ret = 0;
00510 
00511 /*
00512  * shift by count / limb_size
00513  */
00514 if( v0 > 0 )
00515 {
00516 for( i = X->n - 1; i >= v0; i-- )
00517 X->p[i] = X->p[i - v0];
00518 
00519 for( ; i >= 0; i-- )
00520 X->p[i] = 0;
00521 }
00522 
00523 /*
00524  * shift by count % limb_size
00525  */
00526 if( t1 > 0 )
00527 {
00528 for( i = v0; i < X->n; i++ )
00529 {
00530 r1 = X->p[i] >> (biL - t1);
00531 X->p[i] <<= t1;
00532 X->p[i] |= r0;
00533 r0 = r1;
00534 }
00535 }
00536 
00537 cleanup:
00538 
00539 return( ret );
00540 }
00541 
00542 /*
00543  * Right-shift: X >>= count
00544  */
00545 int mpi_shift_r( mpi *X, int count )
00546 {
00547 int i, v0, v1;
00548 t_int r0 = 0, r1;
00549 
00550 v0 = count / biL;
00551 v1 = count & (biL - 1);
00552 
00553 /*
00554  * shift by count / limb_size
00555  */
00556 if( v0 > 0 )
00557 {
00558 for( i = 0; i < X->n - v0; i++ )
00559 X->p[i] = X->p[i + v0];
00560 
00561 for( ; i < X->n; i++ )
00562 X->p[i] = 0;
00563 }
00564 
00565 /*
00566  * shift by count % limb_size
00567  */
00568 if( v1 > 0 )
00569 {
00570 for( i = X->n - 1; i >= 0; i-- )
00571 {
00572 r1 = X->p[i] << (biL - v1);
00573 X->p[i] >>= v1;
00574 X->p[i] |= r0;
00575 r0 = r1;
00576 }
00577 }
00578 
00579 return( 0 );
00580 }
00581 
00582 /*
00583  * Compare unsigned values
00584  */
00585 int mpi_cmp_abs( mpi *X, mpi *Y )
00586 {
00587 int i, j;
00588 
00589 for( i = X->n - 1; i >= 0; i-- )
00590 if( X->p[i] != 0 )
00591 break;
00592 
00593 for( j = Y->n - 1; j >= 0; j-- )
00594 if( Y->p[j] != 0 )
00595 break;
00596 
00597 if( i < 0 && j < 0 )
00598 return( 0 );
00599 
00600 if( i > j ) return( 1 );
00601 if( j > i ) return( -1 );
00602 
00603 for( ; i >= 0; i-- )
00604 {
00605 if( X->p[i] > Y->p[i] ) return( 1 );
00606 if( X->p[i] < Y->p[i] ) return( -1 );
00607 }
00608 
00609 return( 0 );
00610 }
00611 
00612 /*
00613  * Compare signed values
00614  */
00615 int mpi_cmp_mpi( 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( X->s );
00631 if( j > i ) return( -X->s );
00632 
00633 if( X->s > 0 && Y->s < 0 ) return( 1 );
00634 if( Y->s > 0 && X->s < 0 ) return( -1 );
00635 
00636 for( ; i >= 0; i-- )
00637 {
00638 if( X->p[i] > Y->p[i] ) return( X->s );
00639 if( X->p[i] < Y->p[i] ) return( -X->s );
00640 }
00641 
00642 return( 0 );
00643 }
00644 
00645 /*
00646  * Compare signed values
00647  */
00648 int mpi_cmp_int( mpi *X, int z )
00649 {
00650 mpi Y;
00651 t_int p[1];
00652 
00653 *p = ( z < 0 ) ? -z : z;
00654 Y.s = ( z < 0 ) ? -1 : 1;
00655 Y.n = 1;
00656 Y.p = p;
00657 
00658 return( mpi_cmp_mpi( X, &Y ) );
00659 }
00660 
00661 /*
00662  * Unsigned addition: X = |A| + |B| (HAC 14.7)
00663  */
00664 int mpi_add_abs( mpi *X, mpi *A, mpi *B )
00665 {
00666 int ret, i, j;
00667 t_int *o, *p, c;
00668 
00669 if( X == B )
00670 {
00671 mpi *T = A; A = X; B = T;
00672 }
00673 
00674 if( X != A )
00675 MPI_CHK( mpi_copy( X, A ) );
00676 
00677 for( j = B->n - 1; j >= 0; j-- )
00678 if( B->p[j] != 0 )
00679 break;
00680 
00681 MPI_CHK( mpi_grow( X, j + 1 ) );
00682 
00683 o = B->p; p = X->p; c = 0;
00684 
00685 for( i = 0; i <= j; i++, o++, p++ )
00686 {
00687 *p += c; c = ( *p < c );
00688 *p += *o; c += ( *p < *o );
00689 }
00690 
00691 while( c != 0 )
00692 {
00693 if( i >= X->n )
00694 {
00695 MPI_CHK( mpi_grow( X, i + 1 ) );
00696 p = X->p + i;
00697 }
00698 
00699 *p += c; c = ( *p < c ); i++;
00700 }
00701 
00702 cleanup:
00703 
00704 return( ret );
00705 }
00706 
00707 /*
00708  * Helper for mpi substraction
00709  */
00710 static void mpi_sub_hlp( int n, t_int *s, t_int *d )
00711 {
00712 int i;
00713 t_int c, z;
00714 
00715 for( i = c = 0; i < n; i++, s++, d++ )
00716 {
00717 z = ( *d < c ); *d -= c;
00718 c = ( *d < *s ) + z; *d -= *s;
00719 }
00720 
00721 while( c != 0 )
00722 {
00723 z = ( *d < c ); *d -= c;
00724 c = z; i++; d++;
00725 }
00726 }
00727 
00728 /*
00729  * Unsigned substraction: X = |A| - |B| (HAC 14.9)
00730  */
00731 int mpi_sub_abs( mpi *X, mpi *A, mpi *B )
00732 {
00733 mpi TB;
00734 int ret, n;
00735 
00736 if( mpi_cmp_abs( A, B ) < 0 )
00737 return( XYSSL_ERR_MPI_NEGATIVE_VALUE );
00738 
00739 mpi_init( &TB, NULL );
00740 
00741 if( X == B )
00742 {
00743 MPI_CHK( mpi_copy( &TB, B ) );
00744 B = &TB;
00745 }
00746 
00747 if( X != A )
00748 MPI_CHK( mpi_copy( X, A ) );
00749 
00750 ret = 0;
00751 
00752 for( n = B->n - 1; n >= 0; n-- )
00753 if( B->p[n] != 0 )
00754 break;
00755 
00756 mpi_sub_hlp( n + 1, B->p, X->p );
00757 
00758 cleanup:
00759 
00760 mpi_free( &TB, NULL );
00761 
00762 return( ret );
00763 }
00764 
00765 /*
00766  * Signed addition: X = A + B
00767  */
00768 int mpi_add_mpi( mpi *X, mpi *A, mpi *B )
00769 {
00770 int ret, s = A->s;
00771 
00772 if( A->s * B->s < 0 )
00773 {
00774 if( mpi_cmp_abs( A, B ) >= 0 )
00775 {
00776 MPI_CHK( mpi_sub_abs( X, A, B ) );
00777 X->s = s;
00778 }
00779 else
00780 {
00781 MPI_CHK( mpi_sub_abs( X, B, A ) );
00782 X->s = -s;
00783 }
00784 }
00785 else
00786 {
00787 MPI_CHK( mpi_add_abs( X, A, B ) );
00788 X->s = s;
00789 }
00790 
00791 cleanup:
00792 
00793 return( ret );
00794 }
00795 
00796 /*
00797  * Signed substraction: X = A - B
00798  */
00799 int mpi_sub_mpi( mpi *X, mpi *A, mpi *B )
00800 {
00801 int ret, s = A->s;
00802 
00803 if( A->s * B->s > 0 )
00804 {
00805 if( mpi_cmp_abs( A, B ) >= 0 )
00806 {
00807 MPI_CHK( mpi_sub_abs( X, A, B ) );
00808 X->s = s;
00809 }
00810 else
00811 {
00812 MPI_CHK( mpi_sub_abs( X, B, A ) );
00813 X->s = -s;
00814 }
00815 }
00816 else
00817 {
00818 MPI_CHK( mpi_add_abs( X, A, B ) );
00819 X->s = s;
00820 }
00821 
00822 cleanup:
00823 
00824 return( ret );
00825 }
00826 
00827 /*
00828  * Signed addition: X = A + b
00829  */
00830 int mpi_add_int( mpi *X, mpi *A, int b )
00831 {
00832 mpi _B;
00833 t_int p[1];
00834 
00835 p[0] = ( b < 0 ) ? -b : b;
00836 _B.s = ( b < 0 ) ? -1 : 1;
00837 _B.n = 1;
00838 _B.p = p;
00839 
00840 return( mpi_add_mpi( X, A, &_B ) );
00841 }
00842 
00843 /*
00844  * Signed substraction: X = A - b
00845  */
00846 int mpi_sub_int( mpi *X, mpi *A, int b )
00847 {
00848 mpi _B;
00849 t_int p[1];
00850 
00851 p[0] = ( b < 0 ) ? -b : b;
00852 _B.s = ( b < 0 ) ? -1 : 1;
00853 _B.n = 1;
00854 _B.p = p;
00855 
00856 return( mpi_sub_mpi( X, A, &_B ) );
00857 }
00858 
00859 /*
00860  * Helper for mpi multiplication
00861  */ 
00862 static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
00863 {
00864 t_int c = 0, t = 0;
00865 
00866 #if defined(MULADDC_HUIT)
00867 for( ; i >= 8; i -= 8 )
00868 {
00869 MULADDC_INIT
00870 MULADDC_HUIT
00871 MULADDC_STOP
00872 }
00873 
00874 for( ; i > 0; i-- )
00875 {
00876 MULADDC_INIT
00877 MULADDC_CORE
00878 MULADDC_STOP
00879 }
00880 #else
00881 for( ; i >= 16; i -= 16 )
00882 {
00883 MULADDC_INIT
00884 MULADDC_CORE MULADDC_CORE
00885 MULADDC_CORE MULADDC_CORE
00886 MULADDC_CORE MULADDC_CORE
00887 MULADDC_CORE MULADDC_CORE
00888 
00889 MULADDC_CORE MULADDC_CORE
00890 MULADDC_CORE MULADDC_CORE
00891 MULADDC_CORE MULADDC_CORE
00892 MULADDC_CORE MULADDC_CORE
00893 MULADDC_STOP
00894 }
00895 
00896 for( ; i >= 8; i -= 8 )
00897 {
00898 MULADDC_INIT
00899 MULADDC_CORE MULADDC_CORE
00900 MULADDC_CORE MULADDC_CORE
00901 
00902 MULADDC_CORE MULADDC_CORE
00903 MULADDC_CORE MULADDC_CORE
00904 MULADDC_STOP
00905 }
00906 
00907 for( ; i > 0; i-- )
00908 {
00909 MULADDC_INIT
00910 MULADDC_CORE
00911 MULADDC_STOP
00912 }
00913 #endif
00914 
00915 t++;
00916 
00917 do {
00918 *d += c; c = ( *d < c ); d++;
00919 }
00920 while( c != 0 );
00921 }
00922 
00923 /*
00924  * Baseline multiplication: X = A * B (HAC 14.12)
00925  */
00926 int mpi_mul_mpi( mpi *X, mpi *A, mpi *B )
00927 {
00928 int ret, i, j;
00929 mpi TA, TB;
00930 
00931 mpi_init( &TA, &TB, NULL );
00932 
00933 if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
00934 if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
00935 
00936 for( i = A->n - 1; i >= 0; i-- )
00937 if( A->p[i] != 0 )
00938 break;
00939 
00940 for( j = B->n - 1; j >= 0; j-- )
00941 if( B->p[j] != 0 )
00942 break;
00943 
00944 MPI_CHK( mpi_grow( X, i + j + 2 ) );
00945 MPI_CHK( mpi_lset( X, 0 ) );
00946 
00947 for( i++; j >= 0; j-- )
00948 mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
00949 
00950 X->s = A->s * B->s;
00951 
00952 cleanup:
00953 
00954 mpi_free( &TB, &TA, NULL );
00955 
00956 return( ret );
00957 }
00958 
00959 /*
00960  * Baseline multiplication: X = A * b
00961  */
00962 int mpi_mul_int( mpi *X, mpi *A, t_int b )
00963 {
00964 mpi _B;
00965 t_int p[1];
00966 
00967 _B.s = 1;
00968 _B.n = 1;
00969 _B.p = p;
00970 p[0] = b;
00971 
00972 return( mpi_mul_mpi( X, A, &_B ) );
00973 }
00974 
00975 /*
00976  * Division by mpi: A = Q * B + R (HAC 14.20)
00977  */
00978 int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B )
00979 {
00980 int ret, i, n, t, k;
00981 mpi X, Y, Z, T1, T2;
00982 
00983 if( mpi_cmp_int( B, 0 ) == 0 )
00984 return( XYSSL_ERR_MPI_DIVISION_BY_ZERO );
00985 
00986 mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
00987 
00988 if( mpi_cmp_abs( A, B ) < 0 )
00989 {
00990 if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
00991 if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
00992 return( 0 );
00993 }
00994 
00995 MPI_CHK( mpi_copy( &X, A ) );
00996 MPI_CHK( mpi_copy( &Y, B ) );
00997 X.s = Y.s = 1;
00998 
00999 MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
01000 MPI_CHK( mpi_lset( &Z, 0 ) );
01001 MPI_CHK( mpi_grow( &T1, 2 ) );
01002 MPI_CHK( mpi_grow( &T2, 3 ) );
01003 
01004 k = mpi_msb( &Y ) % biL;
01005 if( k < (int) biL - 1 )
01006 {
01007 k = biL - 1 - k;
01008 MPI_CHK( mpi_shift_l( &X, k ) );
01009 MPI_CHK( mpi_shift_l( &Y, k ) );
01010 }
01011 else k = 0;
01012 
01013 n = X.n - 1;
01014 t = Y.n - 1;
01015 mpi_shift_l( &Y, biL * (n - t) );
01016 
01017 while( mpi_cmp_mpi( &X, &Y ) >= 0 )
01018 {
01019 Z.p[n - t]++;
01020 mpi_sub_mpi( &X, &X, &Y );
01021 }
01022 mpi_shift_r( &Y, biL * (n - t) );
01023 
01024 for( i = n; i > t ; i-- )
01025 {
01026 if( X.p[i] >= Y.p[t] )
01027 Z.p[i - t - 1] = ~0;
01028 else
01029 {
01030 #if defined(XYSSL_HAVE_LONGLONG)
01031 t_dbl r;
01032 
01033 r = (t_dbl) X.p[i] << biL;
01034 r |= (t_dbl) X.p[i - 1];
01035 r /= Y.p[t];
01036 if( r > ((t_dbl) 1 << biL) - 1)
01037 r = ((t_dbl) 1 << biL) - 1;
01038 
01039 Z.p[i - t - 1] = (t_int) r;
01040 #else
01041 /*
01042  * __udiv_qrnnd_c, from gmp/longlong.h
01043  */
01044 t_int q0, q1, r0, r1;
01045 t_int d0, d1, d, m;
01046 
01047 d = Y.p[t];
01048 d0 = ( d << biH ) >> biH;
01049 d1 = ( d >> biH );
01050 
01051 q1 = X.p[i] / d1;
01052 r1 = X.p[i] - d1 * q1;
01053 r1 <<= biH;
01054 r1 |= ( X.p[i - 1] >> biH );
01055 
01056 m = q1 * d0;
01057 if( r1 < m )
01058 {
01059 q1--, r1 += d;
01060 while( r1 >= d && r1 < m )
01061 q1--, r1 += d;
01062 }
01063 r1 -= m;
01064 
01065 q0 = r1 / d1;
01066 r0 = r1 - d1 * q0;
01067 r0 <<= biH;
01068 r0 |= ( X.p[i - 1] << biH ) >> biH;
01069 
01070 m = q0 * d0;
01071 if( r0 < m )
01072 {
01073 q0--, r0 += d;
01074 while( r0 >= d && r0 < m )
01075 q0--, r0 += d;
01076 }
01077 r0 -= m;
01078 
01079 Z.p[i - t - 1] = ( q1 << biH ) | q0;
01080 #endif
01081 }
01082 
01083 Z.p[i - t - 1]++;
01084 do
01085 {
01086 Z.p[i - t - 1]--;
01087 
01088 MPI_CHK( mpi_lset( &T1, 0 ) );
01089 T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
01090 T1.p[1] = Y.p[t];
01091 MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
01092 
01093 MPI_CHK( mpi_lset( &T2, 0 ) );
01094 T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
01095 T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
01096 T2.p[2] = X.p[i];
01097 }
01098 while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
01099 
01100 MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
01101 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
01102 MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
01103 
01104 if( mpi_cmp_int( &X, 0 ) < 0 )
01105 {
01106 MPI_CHK( mpi_copy( &T1, &Y ) );
01107 MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
01108 MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
01109 Z.p[i - t - 1]--;
01110 }
01111 }
01112 
01113 if( Q != NULL )
01114 {
01115 mpi_copy( Q, &Z );
01116 Q->s = A->s * B->s;
01117 }
01118 
01119 if( R != NULL )
01120 {
01121 mpi_shift_r( &X, k );
01122 mpi_copy( R, &X );
01123 
01124 R->s = A->s;
01125 if( mpi_cmp_int( R, 0 ) == 0 )
01126 R->s = 1;
01127 }
01128 
01129 cleanup:
01130 
01131 mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
01132 
01133 return( ret );
01134 }
01135 
01136 /*
01137  * Division by int: A = Q * b + R
01138  *
01139  * Returns 0 if successful
01140  * 1 if memory allocation failed
01141  * XYSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
01142  */
01143 int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b )
01144 {
01145 mpi _B;
01146 t_int p[1];
01147 
01148 p[0] = ( b < 0 ) ? -b : b;
01149 _B.s = ( b < 0 ) ? -1 : 1;
01150 _B.n = 1;
01151 _B.p = p;
01152 
01153 return( mpi_div_mpi( Q, R, A, &_B ) );
01154 }
01155 
01156 /*
01157  * Modulo: R = A mod B
01158  */
01159 int mpi_mod_mpi( mpi *R, mpi *A, mpi *B )
01160 {
01161 int ret;
01162 
01163 MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
01164 
01165 while( mpi_cmp_int( R, 0 ) < 0 )
01166 MPI_CHK( mpi_add_mpi( R, R, B ) );
01167 
01168 while( mpi_cmp_mpi( R, B ) >= 0 )
01169 MPI_CHK( mpi_sub_mpi( R, R, B ) );
01170 
01171 cleanup:
01172 
01173 return( ret );
01174 }
01175 
01176 /*
01177  * Modulo: r = A mod b
01178  */
01179 int mpi_mod_int( t_int *r, mpi *A, int b )
01180 {
01181 int i;
01182 t_int x, y, z;
01183 
01184 if( b == 0 )
01185 return( XYSSL_ERR_MPI_DIVISION_BY_ZERO );
01186 
01187 if( b < 0 )
01188 b = -b;
01189 
01190 /*
01191  * handle trivial cases
01192  */
01193 if( b == 1 )
01194 {
01195 *r = 0;
01196 return( 0 );
01197 }
01198 
01199 if( b == 2 )
01200 {
01201 *r = A->p[0] & 1;
01202 return( 0 );
01203 }
01204 
01205 /*
01206  * general case
01207  */
01208 for( i = A->n - 1, y = 0; i >= 0; i-- )
01209 {
01210 x = A->p[i];
01211 y = ( y << biH ) | ( x >> biH );
01212 z = y / b;
01213 y -= z * b;
01214 
01215 x <<= biH;
01216 y = ( y << biH ) | ( x >> biH );
01217 z = y / b;
01218 y -= z * b;
01219 }
01220 
01221 *r = y;
01222 
01223 return( 0 );
01224 }
01225 
01226 /*
01227  * Fast Montgomery initialization (thanks to Tom St Denis)
01228  */
01229 static void mpi_montg_init( t_int *mm, mpi *N )
01230 {
01231 t_int x, m0 = N->p[0];
01232 
01233 x = m0;
01234 x += ( ( m0 + 2 ) & 4 ) << 1;
01235 x *= ( 2 - ( m0 * x ) );
01236 
01237 if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
01238 if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
01239 if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
01240 
01241 *mm = ~x + 1;
01242 }
01243 
01244 /*
01245  * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
01246  */
01247 static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T )
01248 {
01249 int i, n, m;
01250 t_int u0, u1, *d;
01251 
01252 memset( T->p, 0, T->n * ciL );
01253 
01254 d = T->p;
01255 n = N->n;
01256 m = ( B->n < n ) ? B->n : n;
01257 
01258 for( i = 0; i < n; i++ )
01259 {
01260 /*
01261  * T = (T + u0*B + u1*N) / 2^biL
01262  */
01263 u0 = A->p[i];
01264 u1 = ( d[0] + u0 * B->p[0] ) * mm;
01265 
01266 mpi_mul_hlp( m, B->p, d, u0 );
01267 mpi_mul_hlp( n, N->p, d, u1 );
01268 
01269 *d++ = u0; d[n + 1] = 0;
01270 }
01271 
01272 memcpy( A->p, d, (n + 1) * ciL );
01273 
01274 if( mpi_cmp_abs( A, N ) >= 0 )
01275 mpi_sub_hlp( n, N->p, A->p );
01276 else
01277 /* prevent timing attacks */
01278 mpi_sub_hlp( n, A->p, T->p );
01279 }
01280 
01281 /*
01282  * Montgomery reduction: A = A * R^-1 mod N
01283  */
01284 static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T )
01285 {
01286 t_int z = 1;
01287 mpi U;
01288 
01289 U.n = U.s = z;
01290 U.p = &z;
01291 
01292 mpi_montmul( A, &U, N, mm, T );
01293 }
01294 
01295 /*
01296  * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
01297  */
01298 int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR )
01299 {
01300 int ret, i, j, wsize, wbits;
01301 int bufsize, nblimbs, nbits;
01302 t_int ei, mm, state;
01303 mpi RR, T, W[64];
01304 
01305 if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
01306 return( XYSSL_ERR_MPI_BAD_INPUT_DATA );
01307 
01308 /*
01309  * Init temps and window size
01310  */
01311 mpi_montg_init( &mm, N );
01312 mpi_init( &RR, &T, NULL );
01313 memset( W, 0, sizeof( W ) );
01314 
01315 i = mpi_msb( E );
01316 
01317 wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
01318 ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1;
01319 
01320 j = N->n + 1;
01321 MPI_CHK( mpi_grow( X, j ) );
01322 MPI_CHK( mpi_grow( &W[1], j ) );
01323 MPI_CHK( mpi_grow( &T, j * 2 ) );
01324 
01325 /*
01326  * If 1st call, pre-compute R^2 mod N
01327  */
01328 if( _RR == NULL || _RR->p == NULL )
01329 {
01330 MPI_CHK( mpi_lset( &RR, 1 ) );
01331 MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
01332 MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
01333 
01334 if( _RR != NULL )
01335 memcpy( _RR, &RR, sizeof( mpi ) );
01336 }
01337 else
01338 memcpy( &RR, _RR, sizeof( mpi ) );
01339 
01340 /*
01341  * W[1] = A * R^2 * R^-1 mod N = A * R mod N
01342  */
01343 if( mpi_cmp_mpi( A, N ) >= 0 )
01344 mpi_mod_mpi( &W[1], A, N );
01345 else mpi_copy( &W[1], A );
01346 
01347 mpi_montmul( &W[1], &RR, N, mm, &T );
01348 
01349 /*
01350  * X = R^2 * R^-1 mod N = R mod N
01351  */
01352 MPI_CHK( mpi_copy( X, &RR ) );
01353 mpi_montred( X, N, mm, &T );
01354 
01355 if( wsize > 1 )
01356 {
01357 /*
01358  * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
01359  */
01360 j = 1 << (wsize - 1);
01361 
01362 MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
01363 MPI_CHK( mpi_copy( &W[j], &W[1] ) );
01364 
01365 for( i = 0; i < wsize - 1; i++ )
01366 mpi_montmul( &W[j], &W[j], N, mm, &T );
01367 
01368 /*
01369  * W[i] = W[i - 1] * W[1]
01370  */
01371 for( i = j + 1; i < (1 << wsize); i++ )
01372 {
01373 MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
01374 MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
01375 
01376 mpi_montmul( &W[i], &W[1], N, mm, &T );
01377 }
01378 }
01379 
01380 nblimbs = E->n;
01381 bufsize = 0;
01382 nbits = 0;
01383 wbits = 0;
01384 state = 0;
01385 
01386 while( 1 )
01387 {
01388 if( bufsize == 0 )
01389 {
01390 if( nblimbs-- == 0 )
01391 break;
01392 
01393 bufsize = sizeof( t_int ) << 3;
01394 }
01395 
01396 bufsize--;
01397 
01398 ei = (E->p[nblimbs] >> bufsize) & 1;
01399 
01400 /*
01401  * skip leading 0s
01402  */
01403 if( ei == 0 && state == 0 )
01404 continue;
01405 
01406 if( ei == 0 && state == 1 )
01407 {
01408 /*
01409  * out of window, square X
01410  */
01411 mpi_montmul( X, X, N, mm, &T );
01412 continue;
01413 }
01414 
01415 /*
01416  * add ei to current window
01417  */
01418 state = 2;
01419 
01420 nbits++;
01421 wbits |= (ei << (wsize - nbits));
01422 
01423 if( nbits == wsize )
01424 {
01425 /*
01426  * X = X^wsize R^-1 mod N
01427  */
01428 for( i = 0; i < wsize; i++ )
01429 mpi_montmul( X, X, N, mm, &T );
01430 
01431 /*
01432  * X = X * W[wbits] R^-1 mod N
01433  */
01434 mpi_montmul( X, &W[wbits], N, mm, &T );
01435 
01436 state--;
01437 nbits = 0;
01438 wbits = 0;
01439 }
01440 }
01441 
01442 /*
01443  * process the remaining bits
01444  */
01445 for( i = 0; i < nbits; i++ )
01446 {
01447 mpi_montmul( X, X, N, mm, &T );
01448 
01449 wbits <<= 1;
01450 
01451 if( (wbits & (1 << wsize)) != 0 )
01452 mpi_montmul( X, &W[1], N, mm, &T );
01453 }
01454 
01455 /*
01456  * X = A^E * R * R^-1 mod N = A^E mod N
01457  */
01458 mpi_montred( X, N, mm, &T );
01459 
01460 cleanup:
01461 
01462 for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
01463 mpi_free( &W[i], NULL );
01464 
01465 if( _RR != NULL )
01466 mpi_free( &W[1], &T, NULL );
01467 else mpi_free( &W[1], &T, &RR, NULL );
01468 
01469 return( ret );
01470 }
01471 
01472 #if defined(XYSSL_GENPRIME)
01473 
01474 /*
01475  * Greatest common divisor: G = gcd(A, B) (HAC 14.54)
01476  */
01477 int mpi_gcd( mpi *G, mpi *A, mpi *B )
01478 {
01479 int ret;
01480 mpi TG, TA, TB;
01481 
01482 mpi_init( &TG, &TA, &TB, NULL );
01483 
01484 MPI_CHK( mpi_lset( &TG, 1 ) );
01485 MPI_CHK( mpi_copy( &TA, A ) );
01486 MPI_CHK( mpi_copy( &TB, B ) );
01487 
01488 TA.s = TB.s = 1;
01489 
01490 while( mpi_cmp_int( &TA, 0 ) != 0 )
01491 {
01492 while( ( TA.p[0] & 1 ) == 0 ) MPI_CHK( mpi_shift_r( &TA, 1 ) );
01493 while( ( TB.p[0] & 1 ) == 0 ) MPI_CHK( mpi_shift_r( &TB, 1 ) );
01494 
01495 if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
01496 {
01497 MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
01498 MPI_CHK( mpi_shift_r( &TA, 1 ) );
01499 }
01500 else
01501 {
01502 MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
01503 MPI_CHK( mpi_shift_r( &TB, 1 ) );
01504 }
01505 }
01506 
01507 MPI_CHK( mpi_mul_mpi( G, &TG, &TB ) );
01508 
01509 cleanup:
01510 
01511 mpi_free( &TB, &TA, &TG, NULL );
01512 
01513 return( ret );
01514 }
01515 
01516 /*
01517  * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64)
01518  */
01519 int mpi_inv_mod( mpi *X, mpi *A, mpi *N )
01520 {
01521 int ret;
01522 mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
01523 
01524 if( mpi_cmp_int( N, 0 ) <= 0 )
01525 return( XYSSL_ERR_MPI_BAD_INPUT_DATA );
01526 
01527 mpi_init( &TA, &TU, &U1, &U2, &G,
01528 &TB, &TV, &V1, &V2, NULL );
01529 
01530 MPI_CHK( mpi_gcd( &G, A, N ) );
01531 
01532 if( mpi_cmp_int( &G, 1 ) != 0 )
01533 {
01534 ret = XYSSL_ERR_MPI_NOT_ACCEPTABLE;
01535 goto cleanup;
01536 }
01537 
01538 MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
01539 MPI_CHK( mpi_copy( &TU, &TA ) );
01540 MPI_CHK( mpi_copy( &TB, N ) );
01541 MPI_CHK( mpi_copy( &TV, N ) );
01542 
01543 MPI_CHK( mpi_lset( &U1, 1 ) );
01544 MPI_CHK( mpi_lset( &U2, 0 ) );
01545 MPI_CHK( mpi_lset( &V1, 0 ) );
01546 MPI_CHK( mpi_lset( &V2, 1 ) );
01547 
01548 do
01549 {
01550 while( ( TU.p[0] & 1 ) == 0 )
01551 {
01552 MPI_CHK( mpi_shift_r( &TU, 1 ) );
01553 
01554 if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
01555 {
01556 MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
01557 MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
01558 }
01559 
01560 MPI_CHK( mpi_shift_r( &U1, 1 ) );
01561 MPI_CHK( mpi_shift_r( &U2, 1 ) );
01562 }
01563 
01564 while( ( TV.p[0] & 1 ) == 0 )
01565 {
01566 MPI_CHK( mpi_shift_r( &TV, 1 ) );
01567 
01568 if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
01569 {
01570 MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
01571 MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
01572 }
01573 
01574 MPI_CHK( mpi_shift_r( &V1, 1 ) );
01575 MPI_CHK( mpi_shift_r( &V2, 1 ) );
01576 }
01577 
01578 if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
01579 {
01580 MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
01581 MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
01582 MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
01583 }
01584 else
01585 {
01586 MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
01587 MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
01588 MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
01589 }
01590 }
01591 while( mpi_cmp_int( &TU, 0 ) != 0 );
01592 
01593 while( mpi_cmp_int( &V1, 0 ) < 0 )
01594 MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
01595 
01596 while( mpi_cmp_mpi( &V1, N ) >= 0 )
01597 MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
01598 
01599 MPI_CHK( mpi_copy( X, &V1 ) );
01600 
01601 cleanup:
01602 
01603 mpi_free( &V2, &V1, &TV, &TB, &G,
01604 &U2, &U1, &TU, &TA, NULL );
01605 
01606 return( ret );
01607 }
01608 
01609 static const int small_prime[] =
01610 {
01611 3, 5, 7, 11, 13, 17, 19, 23,
01612 29, 31, 37, 41, 43, 47, 53, 59,
01613 61, 67, 71, 73, 79, 83, 89, 97,
01614 101, 103, 107, 109, 113, 127, 131, 137,
01615 139, 149, 151, 157, 163, 167, 173, 179,
01616 181, 191, 193, 197, 199, 211, 223, 227,
01617 229, 233, 239, 241, 251, 257, 263, 269,
01618 271, 277, 281, 283, 293, 307, 311, 313,
01619 317, 331, 337, 347, 349, 353, 359, 367,
01620 373, 379, 383, 389, 397, 401, 409, 419,
01621 421, 431, 433, 439, 443, 449, 457, 461,
01622 463, 467, 479, 487, 491, 499, 503, 509,
01623 521, 523, 541, 547, 557, 563, 569, 571,
01624 577, 587, 593, 599, 601, 607, 613, 617,
01625 619, 631, 641, 643, 647, 653, 659, 661,
01626 673, 677, 683, 691, 701, 709, 719, 727,
01627 733, 739, 743, 751, 757, 761, 769, 773,
01628 787, 797, 809, 811, 821, 823, 827, 829,
01629 839, 853, 857, 859, 863, 877, 881, 883,
01630 887, 907, 911, 919, 929, 937, 941, 947,
01631 953, 967, 971, 977, 983, 991, 997, -103
01632 };
01633 
01634 /*
01635  * Miller-Rabin primality test (HAC 4.24)
01636  */
01637 int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
01638 {
01639 int ret, i, j, n, s, xs;
01640 mpi W, R, T, A, RR;
01641 unsigned char *p;
01642 
01643 if( mpi_cmp_int( X, 0 ) == 0 )
01644 return( 0 );
01645 
01646 mpi_init( &W, &R, &T, &A, &RR, NULL );
01647 
01648 xs = X->s; X->s = 1;
01649 
01650 /*
01651  * test trivial factors first
01652  */
01653 if( ( X->p[0] & 1 ) == 0 )
01654 return( XYSSL_ERR_MPI_NOT_ACCEPTABLE );
01655 
01656 for( i = 0; small_prime[i] > 0; i++ )
01657 {
01658 t_int r;
01659 
01660 if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
01661 return( 0 );
01662 
01663 MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
01664 
01665 if( r == 0 )
01666 return( XYSSL_ERR_MPI_NOT_ACCEPTABLE );
01667 }
01668 
01669 /*
01670  * W = |X| - 1
01671  * R = W >> lsb( W )
01672  */
01673 s = mpi_lsb( &W );
01674 MPI_CHK( mpi_sub_int( &W, X, 1 ) );
01675 MPI_CHK( mpi_copy( &R, &W ) );
01676 MPI_CHK( mpi_shift_r( &R, s ) );
01677 
01678 i = mpi_msb( X );
01679 /*
01680  * HAC, table 4.4
01681  */
01682 n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
01683 ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
01684 ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
01685 
01686 for( i = 0; i < n; i++ )
01687 {
01688 /*
01689  * pick a random A, 1 < A < |X| - 1
01690  */
01691 MPI_CHK( mpi_grow( &A, X->n ) );
01692 
01693 p = (unsigned char *) A.p;
01694 for( j = 0; j < A.n * ciL; j++ )
01695 *p++ = (unsigned char) f_rng( p_rng );
01696 
01697 j = mpi_msb( &A ) - mpi_msb( &W );
01698 MPI_CHK( mpi_shift_r( &A, j + 1 ) );
01699 A.p[0] |= 3;
01700 
01701 /*
01702  * A = A^R mod |X|
01703  */
01704 MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
01705 
01706 if( mpi_cmp_mpi( &A, &W ) == 0 ||
01707 mpi_cmp_int( &A, 1 ) == 0 )
01708 continue;
01709 
01710 j = 1;
01711 while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
01712 {
01713 /*
01714  * A = A * A mod |X|
01715  */
01716 MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
01717 MPI_CHK( mpi_mod_mpi( &A, &T, X ) );
01718 
01719 if( mpi_cmp_int( &A, 1 ) == 0 )
01720 break;
01721 
01722 j++;
01723 }
01724 
01725 /*
01726  * not prime if A != |X| - 1 or A == 1
01727  */
01728 if( mpi_cmp_mpi( &A, &W ) != 0 ||
01729 mpi_cmp_int( &A, 1 ) == 0 )
01730 {
01731 ret = XYSSL_ERR_MPI_NOT_ACCEPTABLE;
01732 break;
01733 }
01734 }
01735 
01736 cleanup:
01737 
01738 X->s = xs;
01739 
01740 mpi_free( &RR, &A, &T, &R, &W, NULL );
01741 
01742 return( ret );
01743 }
01744 
01745 /*
01746  * Prime number generation
01747  */
01748 int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
01749 int (*f_rng)(void *), void *p_rng )
01750 {
01751 int ret, k, n;
01752 unsigned char *p;
01753 mpi Y;
01754 
01755 if( nbits < 3 )
01756 return( XYSSL_ERR_MPI_BAD_INPUT_DATA );
01757 
01758 mpi_init( &Y, NULL );
01759 
01760 n = BITS_TO_LIMBS( nbits );
01761 
01762 MPI_CHK( mpi_grow( X, n ) );
01763 MPI_CHK( mpi_lset( X, 0 ) );
01764 
01765 p = (unsigned char *) X->p;
01766 for( k = 0; k < X->n * ciL; k++ )
01767 *p++ = (unsigned char) f_rng( p_rng );
01768 
01769 k = mpi_msb( X );
01770 if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
01771 if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
01772 
01773 X->p[0] |= 3;
01774 
01775 if( dh_flag == 0 )
01776 {
01777 while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
01778 {
01779 if( ret != XYSSL_ERR_MPI_NOT_ACCEPTABLE )
01780 goto cleanup;
01781 
01782 MPI_CHK( mpi_add_int( X, X, 2 ) );
01783 }
01784 }
01785 else
01786 {
01787 MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
01788 MPI_CHK( mpi_shift_r( &Y, 1 ) );
01789 
01790 while( 1 )
01791 {
01792 if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
01793 {
01794 if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
01795 break;
01796 
01797 if( ret != XYSSL_ERR_MPI_NOT_ACCEPTABLE )
01798 goto cleanup;
01799 }
01800 
01801 if( ret != XYSSL_ERR_MPI_NOT_ACCEPTABLE )
01802 goto cleanup;
01803 
01804 MPI_CHK( mpi_add_int( &Y, X, 1 ) );
01805 MPI_CHK( mpi_add_int( X, X, 2 ) );
01806 MPI_CHK( mpi_shift_r( &Y, 1 ) );
01807 }
01808 }
01809 
01810 cleanup:
01811 
01812 mpi_free( &Y, NULL );
01813 
01814 return( ret );
01815 }
01816 
01817 #endif
01818 
01819 #if defined(XYSSL_SELF_TEST)
01820 
01821 /*
01822  * Checkup routine
01823  */
01824 int mpi_self_test( int verbose )
01825 {
01826 int ret;
01827 mpi A, E, N, X, Y, U, V;
01828 
01829 mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
01830 
01831 MPI_CHK( mpi_read_string( &A, 16,
01832 "EFE021C2645FD1DC586E69184AF4A31E" \
01833 "D5F53E93B5F123FA41680867BA110131" \
01834 "944FE7952E2517337780CB0DB80E61AA" \
01835 "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
01836 
01837 MPI_CHK( mpi_read_string( &E, 16,
01838 "B2E7EFD37075B9F03FF989C7C5051C20" \
01839 "34D2A323810251127E7BF8625A4F49A5" \
01840 "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
01841 "5B5C25763222FEFCCFC38B832366C29E" ) );
01842 
01843 MPI_CHK( mpi_read_string( &N, 16,
01844 "0066A198186C18C10B2F5ED9B522752A" \
01845 "9830B69916E535C8F047518A889A43A5" \
01846 "94B6BED27A168D31D4A52F88925AA8F5" ) );
01847 
01848 MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
01849 
01850 MPI_CHK( mpi_read_string( &U, 16,
01851 "602AB7ECA597A3D6B56FF9829A5E8B85" \
01852 "9E857EA95A03512E2BAE7391688D264A" \
01853 "A5663B0341DB9CCFD2C4C5F421FEC814" \
01854 "8001B72E848A38CAE1C65F78E56ABDEF" \
01855 "E12D3C039B8A02D6BE593F0BBBDA56F1" \
01856 "ECF677152EF804370C1A305CAF3B5BF1" \
01857 "30879B56C61DE584A0F53A2447A51E" ) );
01858 
01859 if( verbose != 0 )
01860 printf( " MPI test #1 (mul_mpi): " );
01861 
01862 if( mpi_cmp_mpi( &X, &U ) != 0 )
01863 {
01864 if( verbose != 0 )
01865 printf( "failed\n" );
01866 
01867 return( 1 );
01868 }
01869 
01870 if( verbose != 0 )
01871 printf( "passed\n" );
01872 
01873 MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
01874 
01875 MPI_CHK( mpi_read_string( &U, 16,
01876 "256567336059E52CAE22925474705F39A94" ) );
01877 
01878 MPI_CHK( mpi_read_string( &V, 16,
01879 "6613F26162223DF488E9CD48CC132C7A" \
01880 "0AC93C701B001B092E4E5B9F73BCD27B" \
01881 "9EE50D0657C77F374E903CDFA4C642" ) );
01882 
01883 if( verbose != 0 )
01884 printf( " MPI test #2 (div_mpi): " );
01885 
01886 if( mpi_cmp_mpi( &X, &U ) != 0 ||
01887 mpi_cmp_mpi( &Y, &V ) != 0 )
01888 {
01889 if( verbose != 0 )
01890 printf( "failed\n" );
01891 
01892 return( 1 );
01893 }
01894 
01895 if( verbose != 0 )
01896 printf( "passed\n" );
01897 
01898 MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
01899 
01900 MPI_CHK( mpi_read_string( &U, 16,
01901 "36E139AEA55215609D2816998ED020BB" \
01902 "BD96C37890F65171D948E9BC7CBAA4D9" \
01903 "325D24D6A3C12710F10A09FA08AB87" ) );
01904 
01905 if( verbose != 0 )
01906 printf( " MPI test #3 (exp_mod): " );
01907 
01908 if( mpi_cmp_mpi( &X, &U ) != 0 )
01909 {
01910 if( verbose != 0 )
01911 printf( "failed\n" );
01912 
01913 return( 1 );
01914 }
01915 
01916 if( verbose != 0 )
01917 printf( "passed\n" );
01918 
01919 MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
01920 
01921 MPI_CHK( mpi_read_string( &U, 16,
01922 "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
01923 "C3DBA76456363A10869622EAC2DD84EC" \
01924 "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
01925 
01926 if( verbose != 0 )
01927 printf( " MPI test #4 (inv_mod): " );
01928 
01929 if( mpi_cmp_mpi( &X, &U ) != 0 )
01930 {
01931 if( verbose != 0 )
01932 printf( "failed\n" );
01933 
01934 return( 1 );
01935 }
01936 
01937 if( verbose != 0 )
01938 printf( "passed\n" );
01939 
01940 cleanup:
01941 
01942 if( ret != 0 && verbose != 0 )
01943 printf( "Unexpected error, return code = %08X\n", ret );
01944 
01945 mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
01946 
01947 if( verbose != 0 )
01948 printf( "\n" );
01949 
01950 return( ret );
01951 }
01952 
01953 #endif
01954 
01955 #endif

Generated on Tue Oct 28 17:03:23 2008 for Mobile-C by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /