Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MiniTLS-GPL by
fp_exptmod.c
00001 /* TomsFastMath, a fast ISO C bignum library. 00002 * 00003 * This project is meant to fill in where LibTomMath 00004 * falls short. That is speed ;-) 00005 * 00006 * This project is public domain and free for all purposes. 00007 * 00008 * Tom St Denis, tomstdenis@gmail.com 00009 */ 00010 #include <tfm.h> 00011 00012 #ifdef TFM_TIMING_RESISTANT 00013 00014 /* timing resistant montgomery ladder based exptmod 00015 00016 Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 00017 */ 00018 static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 00019 { 00020 fp_int R[2]; 00021 fp_digit buf, mp; 00022 int err, bitcnt, digidx, y; 00023 00024 /* now setup montgomery */ 00025 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 00026 return err; 00027 } 00028 00029 fp_init(&R[0]); 00030 fp_init(&R[1]); 00031 00032 /* now we need R mod m */ 00033 fp_montgomery_calc_normalization (&R[0], P); 00034 00035 /* now set R[0][1] to G * R mod m */ 00036 if (fp_cmp_mag(P, G) != FP_GT) { 00037 /* G > P so we reduce it first */ 00038 fp_mod(G, P, &R[1]); 00039 } else { 00040 fp_copy(G, &R[1]); 00041 } 00042 fp_mulmod (&R[1], &R[0], P, &R[1]); 00043 00044 /* for j = t-1 downto 0 do 00045 r_!k = R0*R1; r_k = r_k^2 00046 */ 00047 00048 /* set initial mode and bit cnt */ 00049 bitcnt = 1; 00050 buf = 0; 00051 digidx = X->used - 1; 00052 00053 for (;;) { 00054 /* grab next digit as required */ 00055 if (--bitcnt == 0) { 00056 /* if digidx == -1 we are out of digits so break */ 00057 if (digidx == -1) { 00058 break; 00059 } 00060 /* read next digit and reset bitcnt */ 00061 buf = X->dp[digidx--]; 00062 bitcnt = (int)DIGIT_BIT; 00063 } 00064 00065 /* grab the next msb from the exponent */ 00066 y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 00067 buf <<= (fp_digit)1; 00068 00069 /* do ops */ 00070 fp_mul(&R[0], &R[1], &R[y^1]); fp_montgomery_reduce(&R[y^1], P, mp); 00071 fp_sqr(&R[y], &R[y]); fp_montgomery_reduce(&R[y], P, mp); 00072 } 00073 00074 fp_montgomery_reduce(&R[0], P, mp); 00075 fp_copy(&R[0], Y); 00076 return FP_OKAY; 00077 } 00078 00079 #else 00080 00081 /* y = g**x (mod b) 00082 * Some restrictions... x must be positive and < b 00083 */ 00084 static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 00085 { 00086 fp_int M[64], res; 00087 fp_digit buf, mp; 00088 int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; 00089 00090 /* find window size */ 00091 x = fp_count_bits (X); 00092 if (x <= 21) { 00093 winsize = 1; 00094 } else if (x <= 36) { 00095 winsize = 3; 00096 } else if (x <= 140) { 00097 winsize = 4; 00098 } else if (x <= 450) { 00099 winsize = 5; 00100 } else { 00101 winsize = 6; 00102 } 00103 00104 /* init M array */ 00105 memset(M, 0, sizeof(M)); 00106 00107 /* now setup montgomery */ 00108 if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { 00109 return err; 00110 } 00111 00112 /* setup result */ 00113 fp_init(&res); 00114 00115 /* create M table 00116 * 00117 * The M table contains powers of the input base, e.g. M[x] = G^x mod P 00118 * 00119 * The first half of the table is not computed though accept for M[0] and M[1] 00120 */ 00121 00122 /* now we need R mod m */ 00123 fp_montgomery_calc_normalization (&res, P); 00124 00125 /* now set M[1] to G * R mod m */ 00126 if (fp_cmp_mag(P, G) != FP_GT) { 00127 /* G > P so we reduce it first */ 00128 fp_mod(G, P, &M[1]); 00129 } else { 00130 fp_copy(G, &M[1]); 00131 } 00132 fp_mulmod (&M[1], &res, P, &M[1]); 00133 00134 /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ 00135 fp_copy (&M[1], &M[1 << (winsize - 1)]); 00136 for (x = 0; x < (winsize - 1); x++) { 00137 fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]); 00138 fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); 00139 } 00140 00141 /* create upper table */ 00142 for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { 00143 fp_mul(&M[x - 1], &M[1], &M[x]); 00144 fp_montgomery_reduce(&M[x], P, mp); 00145 } 00146 00147 /* set initial mode and bit cnt */ 00148 mode = 0; 00149 bitcnt = 1; 00150 buf = 0; 00151 digidx = X->used - 1; 00152 bitcpy = 0; 00153 bitbuf = 0; 00154 00155 for (;;) { 00156 /* grab next digit as required */ 00157 if (--bitcnt == 0) { 00158 /* if digidx == -1 we are out of digits so break */ 00159 if (digidx == -1) { 00160 break; 00161 } 00162 /* read next digit and reset bitcnt */ 00163 buf = X->dp[digidx--]; 00164 bitcnt = (int)DIGIT_BIT; 00165 } 00166 00167 /* grab the next msb from the exponent */ 00168 y = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1; 00169 buf <<= (fp_digit)1; 00170 00171 /* if the bit is zero and mode == 0 then we ignore it 00172 * These represent the leading zero bits before the first 1 bit 00173 * in the exponent. Technically this opt is not required but it 00174 * does lower the # of trivial squaring/reductions used 00175 */ 00176 if (mode == 0 && y == 0) { 00177 continue; 00178 } 00179 00180 /* if the bit is zero and mode == 1 then we square */ 00181 if (mode == 1 && y == 0) { 00182 fp_sqr(&res, &res); 00183 fp_montgomery_reduce(&res, P, mp); 00184 continue; 00185 } 00186 00187 /* else we add it to the window */ 00188 bitbuf |= (y << (winsize - ++bitcpy)); 00189 mode = 2; 00190 00191 if (bitcpy == winsize) { 00192 /* ok window is filled so square as required and multiply */ 00193 /* square first */ 00194 for (x = 0; x < winsize; x++) { 00195 fp_sqr(&res, &res); 00196 fp_montgomery_reduce(&res, P, mp); 00197 } 00198 00199 /* then multiply */ 00200 fp_mul(&res, &M[bitbuf], &res); 00201 fp_montgomery_reduce(&res, P, mp); 00202 00203 /* empty window and reset */ 00204 bitcpy = 0; 00205 bitbuf = 0; 00206 mode = 1; 00207 } 00208 } 00209 00210 /* if bits remain then square/multiply */ 00211 if (mode == 2 && bitcpy > 0) { 00212 /* square then multiply if the bit is set */ 00213 for (x = 0; x < bitcpy; x++) { 00214 fp_sqr(&res, &res); 00215 fp_montgomery_reduce(&res, P, mp); 00216 00217 /* get next bit of the window */ 00218 bitbuf <<= 1; 00219 if ((bitbuf & (1 << winsize)) != 0) { 00220 /* then multiply */ 00221 fp_mul(&res, &M[1], &res); 00222 fp_montgomery_reduce(&res, P, mp); 00223 } 00224 } 00225 } 00226 00227 /* fixup result if Montgomery reduction is used 00228 * recall that any value in a Montgomery system is 00229 * actually multiplied by R mod n. So we have 00230 * to reduce one more time to cancel out the factor 00231 * of R. 00232 */ 00233 fp_montgomery_reduce(&res, P, mp); 00234 00235 /* swap res with Y */ 00236 fp_copy (&res, Y); 00237 return FP_OKAY; 00238 } 00239 00240 #endif 00241 00242 00243 int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) 00244 { 00245 fp_int tmp; 00246 int err; 00247 00248 #ifdef TFM_CHECK 00249 /* prevent overflows */ 00250 if (P->used > (FP_SIZE/2)) { 00251 return FP_VAL; 00252 } 00253 #endif 00254 00255 /* is X negative? */ 00256 if (X->sign == FP_NEG) { 00257 /* yes, copy G and invmod it */ 00258 fp_copy(G, &tmp); 00259 if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) { 00260 return err; 00261 } 00262 X->sign = FP_ZPOS; 00263 err = _fp_exptmod(&tmp, X, P, Y); 00264 if (X != Y) { 00265 X->sign = FP_NEG; 00266 } 00267 return err; 00268 } else { 00269 /* Positive exponent so just exptmod */ 00270 return _fp_exptmod(G, X, P, Y); 00271 } 00272 } 00273 00274 /* $Source: /cvs/libtom/tomsfastmath/src/exptmod/fp_exptmod.c,v $ */ 00275 /* $Revision: 1.1 $ */ 00276 /* $Date: 2006/12/31 21:25:53 $ */
Generated on Tue Jul 12 2022 19:20:10 by
1.7.2
