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

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

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4