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