Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib is distributed in the hope that it will be useful, ** 00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 00013 ** GNU Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ***************************************************************************/ 00019 00020 #ifndef __ALGORITHMS_CRYPTO_PMP_H_ 00021 #define __ALGORITHMS_CRYPTO_PMP_H_ 00022 00023 namespace wiselib 00024 { 00025 00026 /* Define here the key bit length for the 00027 * elliptic curve arithmetic operations 00028 * Possible Values: 128, 160, 192 */ 00029 00030 #define KEY_BIT_LEN 128 00031 //#define KEY_BIT_LEN 160 00032 //#define KEY_BIT_LEN 192 00033 00034 /* define here the number of bits on which the processor can operate 00035 * Possible Values 8, 16, 32 */ 00036 00037 //#define EIGHT_BIT_PROCESSOR 00038 //#define SIXTEEN_BIT_PROCESSOR 00039 #define THIRTYTWO_BIT_PROCESSOR 00040 00041 //next the necessary types depending on the processor 00042 //are defined 00043 00044 // START OF 8-bit PROCESSOR 00045 #ifdef EIGHT_BIT_PROCESSOR 00046 00047 /* Type definitions */ 00048 typedef uint8_t NN_DIGIT; 00049 typedef uint16_t NN_DOUBLE_DIGIT; 00050 00051 /* Types for length */ 00052 typedef uint8_t NN_UINT; 00053 typedef uint16_t NN_UINT2; 00054 00055 /* Length of digit in bits */ 00056 #define NN_DIGIT_BITS 8 00057 00058 /* Length of digit in bytes */ 00059 #define NN_DIGIT_LEN (NN_DIGIT_BITS/8) 00060 00061 /* Maximum value of digit */ 00062 #define MAX_NN_DIGIT 0xff 00063 00064 /* Number of digits in key */ 00065 #define KEYDIGITS (KEY_BIT_LEN/NN_DIGIT_BITS) 00066 00067 /* Maximum length in digits */ 00068 #define MAX_NN_DIGITS (KEYDIGITS+1) 00069 00070 /* buffer size 00071 *should be large enough to hold order of base point 00072 */ 00073 #define NUMWORDS MAX_NN_DIGITS 00074 00075 #endif // END OF 8-bit PROCESSOR 00076 00077 //START OF 16-bit PROCESSOR 00078 #ifdef SIXTEEN_BIT_PROCESSOR 00079 00080 /* Type definitions */ 00081 typedef uint16_t NN_DIGIT; 00082 typedef uint32_t NN_DOUBLE_DIGIT; 00083 00084 /* Types for length */ 00085 typedef uint8_t NN_UINT; 00086 typedef uint16_t NN_UINT2; 00087 00088 /* Length of digit in bits */ 00089 #define NN_DIGIT_BITS 16 00090 00091 /* Length of digit in bytes */ 00092 #define NN_DIGIT_LEN (NN_DIGIT_BITS/8) 00093 00094 /* Maximum value of digit */ 00095 #define MAX_NN_DIGIT 0xffff 00096 00097 /* Number of digits in key */ 00098 #define KEYDIGITS (KEY_BIT_LEN/NN_DIGIT_BITS) 00099 00100 /* Maximum length in digits */ 00101 #define MAX_NN_DIGITS (KEYDIGITS+1) 00102 00103 /* buffer size 00104 *should be large enough to hold order of base point 00105 */ 00106 #define NUMWORDS MAX_NN_DIGITS 00107 00108 #endif //END OF 16-bit PROCESSOR 00109 00110 //START of 32-bit PROCESSOR 00111 #ifdef THIRTYTWO_BIT_PROCESSOR 00112 00113 /* Type definitions */ 00114 typedef uint32_t NN_DIGIT; 00115 typedef uint64_t NN_DOUBLE_DIGIT; 00116 00117 /* Types for length */ 00118 typedef uint8_t NN_UINT; 00119 typedef uint16_t NN_UINT2; 00120 00121 /* Length of digit in bits */ 00122 #define NN_DIGIT_BITS 32 00123 00124 /* Length of digit in bytes */ 00125 #define NN_DIGIT_LEN (NN_DIGIT_BITS/8) 00126 00127 /* Maximum value of digit */ 00128 #define MAX_NN_DIGIT 0xffffffff 00129 00130 /* Number of digits in key */ 00131 #define KEYDIGITS (KEY_BIT_LEN/NN_DIGIT_BITS) 00132 00133 /* Maximum length in digits */ 00134 #define MAX_NN_DIGITS (KEYDIGITS+1) 00135 00136 /* buffer size 00137 *should be large enough to hold order of base point 00138 */ 00139 #define NUMWORDS MAX_NN_DIGITS 00140 00141 #endif //END OF 32-bit PROCESSOR 00142 00143 //Base operations 00144 #define MAXIMUM(a,b) ((a) < (b) ? (b) : (a)) 00145 #define DIGIT_MSB(x) (NN_DIGIT)(((x) >> (NN_DIGIT_BITS - 1)) & 1) 00146 #define DIGIT_2MSB(x) (NN_DIGIT)(((x) >> (NN_DIGIT_BITS - 2)) & 3) 00147 #define ASSIGN_DIGIT(a, b, digits) {AssignZero (a, digits); a[0] = b;} 00148 #define EQUAL(a, b, digits) (! NN_Cmp (a, b, digits)) 00149 #define EVEN(a, digits) (((digits) == 0) || ! (a[0] & 1)) 00150 #define DigitMult(b, c) (NN_DOUBLE_DIGIT)(b) * (c) 00151 00152 /* Necessary Structs for elliptic curve operations*/ 00153 00154 //the data structure that defines an elliptic curve 00155 struct Curve 00156 { 00157 // curve's coefficients 00158 NN_DIGIT a[NUMWORDS]; 00159 NN_DIGIT b[NUMWORDS]; 00160 00161 //whether a is -3 00162 bool a_minus3; 00163 00164 //whether a is zero 00165 bool a_zero; 00166 00167 bool a_one; 00168 }; 00169 typedef struct Curve Curve; 00170 00171 //structure for representing elliptic curve points 00172 struct Point 00173 { 00174 // point's coordinates 00175 NN_DIGIT x[NUMWORDS]; 00176 NN_DIGIT y[NUMWORDS]; 00177 }; 00178 typedef struct Point Point; 00179 00180 //all the parameters needed for elliptic curve operations 00181 struct Params 00182 { 00183 // prime modulus 00184 NN_DIGIT p[NUMWORDS]; 00185 00186 // Omega, p = 2^m -omega 00187 NN_DIGIT omega[NUMWORDS]; 00188 00189 // curve over which ECC will be performed 00190 Curve E; 00191 00192 // base point, a point on E of order r 00193 Point G; 00194 00195 // a positive, prime integer dividing the number of points on E 00196 NN_DIGIT r[NUMWORDS]; 00197 }; 00198 typedef struct Params Params; 00199 00200 class PMP 00201 { 00202 public: 00203 00204 //-----------------------UTILITY FUNCTIONS-----------------------------------------// 00205 00206 // test whether the ith bit in a is one 00207 NN_DIGIT b_testbit(NN_DIGIT * a, int16 i) 00208 { 00209 return (*(a + (i / NN_DIGIT_BITS)) & ((NN_DIGIT)1 << (i % NN_DIGIT_BITS))); 00210 } 00211 00212 00213 /* CONVERSIONS */ 00214 00215 /* Decodes character string b into a, where character string is ordered 00216 from most to least significant. 00217 Lengths: a[digits], b[len]. 00218 Assumes b[i] = 0 for i < len - digits * NN_DIGIT_LEN. (Otherwise most 00219 significant bytes are truncated.) 00220 */ 00221 void Decode (NN_DIGIT *a, NN_UINT digits, unsigned char *b, NN_UINT len) 00222 { 00223 NN_DIGIT t; 00224 int8_t j; 00225 uint16_t i, u; 00226 00227 for (i = 0, j = len - 1; i < digits && j >= 0; i++) { 00228 t = 0; 00229 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) 00230 t |= ((NN_DIGIT)b[j]) << u; 00231 a[i] = t; 00232 } 00233 00234 for (; i < digits; i++) 00235 a[i] = 0; 00236 } 00237 00238 /* Encodes b into character string a, where character string is ordered 00239 from most to least significant. 00240 Lengths: a[len], b[digits]. 00241 Assumes NN_Bits (b, digits) <= 8 * len. (Otherwise most significant 00242 digits are truncated.) 00243 */ 00244 void Encode (unsigned char *a, NN_UINT len, NN_DIGIT *b, NN_UINT digits) 00245 { 00246 NN_DIGIT t; 00247 int8_t j; 00248 uint16_t i, u; 00249 00250 for (i = 0, j = len - 1; i < digits && j >= 0; i++) { 00251 t = b[i]; 00252 for (u = 0; j >= 0 && u < NN_DIGIT_BITS; j--, u += 8) 00253 a[j] = (unsigned char)(t >> u); 00254 } 00255 00256 for (; j >= 0; j--) 00257 a[j] = 0; 00258 } 00259 //---------------------------------------------------------------------------// 00260 00261 /* ASSIGNMENTS */ 00262 00263 /* Assigns a = b. 00264 Lengths: a[digits], b[digits]. 00265 */ 00266 void Assign (NN_DIGIT *a, NN_DIGIT *b, NN_UINT digits) 00267 { 00268 memcpy(a, b, digits*NN_DIGIT_LEN); 00269 } 00270 00271 void AssignZero (NN_DIGIT *a, NN_UINT digits) 00272 { 00273 00274 uint8_t i; 00275 00276 for (i = 0; i < digits; i++) 00277 a[i] = 0; 00278 00279 } 00280 00281 /* Assigns a = 2^b. 00282 Lengths: a[digits]. 00283 Requires b < digits * NN_DIGIT_BITS. 00284 */ 00285 void Assign2Exp (NN_DIGIT *a, NN_UINT2 b, NN_UINT digits) 00286 { 00287 AssignZero (a, digits); 00288 00289 if (b >= digits * NN_DIGIT_BITS) 00290 return; 00291 00292 a[b / NN_DIGIT_BITS] = (NN_DIGIT)1 << (b % NN_DIGIT_BITS); 00293 } 00294 00295 void AssignDigit(NN_DIGIT * a, NN_DIGIT b, NN_UINT digits) 00296 { 00297 AssignZero (a, digits); 00298 a[0] = b; 00299 } 00300 00301 //------------------------------------------------------------------------------------// 00302 00303 /* ARITHMETIC OPERATIONS */ 00304 00305 /* Computes a = b + c. Returns carry. 00306 a, b ,c can be same 00307 Lengths: a[digits], b[digits], c[digits]. 00308 */ 00309 NN_DIGIT Add (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits) 00310 { 00311 00312 NN_DIGIT carry, ai; 00313 NN_UINT i; 00314 00315 carry = 0; 00316 00317 for (i = 0; i < digits; i++) { 00318 if ((ai = b[i] + carry) < carry) 00319 ai = c[i]; 00320 else if ((ai += c[i]) < c[i]) 00321 carry = 1; 00322 else 00323 carry = 0; 00324 a[i] = ai; 00325 } 00326 return carry; 00327 } 00328 00329 /* Computes a = b - c. Returns borrow. 00330 a, b, c can be same 00331 Lengths: a[digits], b[digits], c[digits]. 00332 */ 00333 NN_DIGIT Sub (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits) 00334 { 00335 NN_DIGIT ai, borrow; 00336 NN_UINT i; 00337 00338 borrow = 0; 00339 00340 for (i = 0; i < digits; i++) { 00341 if ((ai = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) 00342 ai = MAX_NN_DIGIT - c[i]; 00343 else if ((ai -= c[i]) > (MAX_NN_DIGIT - c[i])) 00344 borrow = 1; 00345 else 00346 borrow = 0; 00347 a[i] = ai; 00348 } 00349 return borrow; 00350 } 00351 00352 /* Computes a = b * c. 00353 a, b, c can be same 00354 Lengths: a[2*digits], b[digits], c[digits]. 00355 Assumes digits < MAX_NN_DIGITS. 00356 */ 00357 void Mult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits) 00358 { 00359 NN_DIGIT t[2*MAX_NN_DIGITS+2]; 00360 NN_UINT bDigits, cDigits, i; 00361 00362 AssignZero (t, 2 * digits); 00363 00364 bDigits = Digits (b, digits); 00365 cDigits = Digits (c, digits); 00366 00367 for (i = 0; i < bDigits; i++) 00368 t[i+cDigits] += AddDigitMult (&t[i], &t[i], b[i], c, cDigits); 00369 00370 Assign (a, t, 2 * digits); 00371 } 00372 00373 /* Computes a = c div d and b = c mod d. 00374 a, c, d can be same 00375 b, c, d can be same 00376 Lengths: a[cDigits], b[dDigits], c[cDigits], d[dDigits]. 00377 Assumes d > 0, cDigits < 2 * MAX_NN_DIGITS, 00378 dDigits < MAX_NN_DIGITS. 00379 */ 00380 void Div (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT cDigits, NN_DIGIT *d, NN_UINT dDigits) 00381 { 00382 NN_DIGIT ai, cc[2*MAX_NN_DIGITS+2], dd[MAX_NN_DIGITS+1], t; 00383 00384 int8_t i; 00385 int8_t ddDigits, shift; 00386 00387 ddDigits = Digits (d, dDigits); 00388 if (ddDigits == 0) 00389 return; 00390 00391 /* Normalize operands.*/ 00392 shift = NN_DIGIT_BITS - DigitBits (d[ddDigits-1]); 00393 AssignZero (cc, ddDigits); 00394 cc[cDigits] = LShift (cc, c, shift, cDigits); 00395 LShift (dd, d, shift, ddDigits); 00396 t = dd[ddDigits-1]; 00397 00398 if (a != NULL) 00399 AssignZero (a, cDigits); 00400 00401 for (i = cDigits-ddDigits; i >= 0; i--) { 00402 /* Underestimate quotient digit and subtract. 00403 */ 00404 if (t == MAX_NN_DIGIT) 00405 ai = cc[i+ddDigits]; 00406 else 00407 DigitDiv (&ai, &cc[i+ddDigits-1], t + 1); 00408 cc[i+ddDigits] -= SubDigitMult (&cc[i], &cc[i], ai, dd, ddDigits); 00409 00410 /* Correct estimate. 00411 */ 00412 while (cc[i+ddDigits] || (Cmp (&cc[i], dd, ddDigits) >= 0)) { 00413 ai++; 00414 cc[i+ddDigits] -= Sub (&cc[i], &cc[i], dd, ddDigits); 00415 } 00416 if (a != NULL) 00417 a[i] = ai; 00418 } 00419 /* Restore result. 00420 */ 00421 AssignZero (b, dDigits); 00422 RShift (b, cc, shift, ddDigits); 00423 } 00424 00425 void Sqr(NN_DIGIT *a, NN_DIGIT *b, NN_UINT digits) 00426 { 00427 00428 NN_DIGIT t[2*MAX_NN_DIGITS]; 00429 NN_UINT bDigits, i; 00430 00431 AssignZero (t, 2 * digits); 00432 00433 bDigits = Digits (b, digits); 00434 00435 for (i = 0; i < bDigits; i++) 00436 t[i+bDigits] += AddDigitMult (&t[i], &t[i], b[i], b, bDigits); 00437 00438 Assign (a, t, 2 * digits); 00439 } 00440 00441 /* Computes a = b * 2^c (i.e., shifts left c bits), returning carry. 00442 a, b can be same 00443 Lengths: a[digits], b[digits]. 00444 Requires c < NN_DIGIT_BITS. 00445 */ 00446 NN_DIGIT LShift (NN_DIGIT *a, NN_DIGIT *b, NN_UINT c, NN_UINT digits) 00447 { 00448 NN_DIGIT bi, carry; 00449 NN_UINT i, t; 00450 00451 if (c >= NN_DIGIT_BITS) 00452 return (0); 00453 00454 t = NN_DIGIT_BITS - c; 00455 00456 carry = 0; 00457 00458 for (i = 0; i < digits; i++) { 00459 bi = b[i]; 00460 a[i] = (bi << c) | carry; 00461 carry = c ? (bi >> t) : 0; 00462 } 00463 00464 return (carry); 00465 } 00466 00467 /* Computes a = b div 2^c (i.e., shifts right c bits), returning carry. 00468 a, b can be same 00469 Lengths: a[digits], b[digits]. 00470 Requires: c < NN_DIGIT_BITS. 00471 */ 00472 NN_DIGIT RShift (NN_DIGIT *a, NN_DIGIT *b, NN_UINT c, NN_UINT digits) 00473 { 00474 NN_DIGIT bi, carry; 00475 int8_t i; 00476 NN_UINT t; 00477 00478 if (c >= NN_DIGIT_BITS) 00479 return (0); 00480 00481 t = NN_DIGIT_BITS - c; 00482 00483 carry = 0; 00484 00485 for (i = digits - 1; i >= 0; i--) { 00486 bi = b[i]; 00487 a[i] = (bi >> c) | carry; 00488 carry = c ? (bi << t) : 0; 00489 } 00490 00491 return (carry); 00492 } 00493 00494 /* Computes a = b + c*d, where c is a digit. Returns carry. 00495 a, b, c can be same 00496 Lengths: a[digits], b[digits], d[digits]. 00497 */ 00498 static NN_DIGIT AddDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c, NN_DIGIT *d, NN_UINT digits) 00499 { 00500 NN_DIGIT carry; 00501 uint16_t i; 00502 NN_DOUBLE_DIGIT t; 00503 00504 //Should copy b to a 00505 if (c == 0) 00506 return (0); 00507 carry = 0; 00508 for (i = 0; i < digits; i++) { 00509 t = DigitMult (c, d[i]); 00510 if ((a[i] = b[i] + carry) < carry) 00511 carry = 1; 00512 else 00513 carry = 0; 00514 if ((a[i] += (t & MAX_NN_DIGIT)) < (t & MAX_NN_DIGIT)) 00515 carry++; 00516 carry += (NN_DIGIT)(t >> NN_DIGIT_BITS); 00517 } 00518 return (carry); 00519 } 00520 00521 00522 //---------------------------------------------------------------------------------// 00523 00524 /* NUMBER THEORY */ 00525 00526 /* Computes a = b mod c. 00527 Lengths: a[cDigits], b[bDigits], c[cDigits]. 00528 Assumes c > 0, bDigits < 2 * MAX_NN_DIGITS, cDigits < MAX_NN_DIGITS. 00529 */ 00530 void Mod (NN_DIGIT *a, NN_DIGIT *b, NN_UINT bDigits, NN_DIGIT *c, NN_UINT cDigits) 00531 { 00532 Div (NULL, a, b, bDigits, c, cDigits); 00533 } 00534 00535 void ModSmall(NN_DIGIT * b, NN_DIGIT * c, NN_UINT digits) 00536 { 00537 while (Cmp(b, c, digits) > 0) 00538 Sub(b, b, c, digits); 00539 } 00540 00541 //Computes a = (b + c) mod d. 00542 //a, b, c can be same 00543 //Assumption: b,c is in [0, d) 00544 void ModAdd(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * c, NN_DIGIT * d, NN_UINT digits) 00545 { 00546 NN_DIGIT tmp[MAX_NN_DIGITS]; 00547 NN_DIGIT carry; 00548 00549 carry = Add(tmp, b, c, digits); 00550 if (carry) 00551 Sub(a, tmp, d, digits); 00552 else if (Cmp(tmp, d, digits) >= 0) 00553 Sub(a, tmp, d, digits); 00554 else 00555 Assign(a, tmp, digits); 00556 } 00557 00558 //Computes a = (b - c) mod d. 00559 //Assume b and c are all smaller than d 00560 //always return positive value 00561 void ModSub(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * c, NN_DIGIT * d, NN_UINT digits) 00562 { 00563 NN_DIGIT tmp[MAX_NN_DIGITS]; 00564 NN_DIGIT borrow; 00565 00566 borrow = Sub(tmp, b, c, digits); 00567 if (borrow) 00568 Add(a, tmp, d, digits); 00569 else 00570 Assign(a, tmp, digits); 00571 } 00572 00573 //Computes a = -b mod c 00574 void ModNeg(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * c, NN_UINT digits) 00575 { 00576 ModSub(a,c,b,c,digits); 00577 } 00578 00579 /* Computes a = b * c mod d. 00580 a, b, c can be same 00581 Lengths: a[digits], b[digits], c[digits], d[digits]. 00582 Assumes d > 0, digits < MAX_NN_DIGITS. 00583 */ 00584 void ModMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d, NN_UINT digits) 00585 { 00586 NN_DIGIT t[2*MAX_NN_DIGITS]; 00587 00588 //memset(t, 0, 2*MAX_NN_DIGITS*NN_DIGIT_LEN); 00589 t[2*MAX_NN_DIGITS-1]=0; 00590 t[2*MAX_NN_DIGITS-2]=0; 00591 Mult (t, b, c, digits); 00592 Mod (a, t, 2 * digits, d, digits); 00593 } 00594 00595 //Computes a = (b / c) mod d 00596 void ModDiv(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * c, NN_DIGIT * d, NN_UINT digits) 00597 { 00598 ModDivOpt(a,b,c,d,digits); 00599 } 00600 00601 /* Computes a = b^c mod d. 00602 Lengths: a[dDigits], b[dDigits], c[cDigits], d[dDigits]. 00603 Assumes d > 0, cDigits > 0, dDigits < MAX_NN_DIGITS. 00604 */ 00605 void ModExp (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT cDigits, NN_DIGIT *d, NN_UINT dDigits) 00606 { 00607 NN_DIGIT bPower[3][MAX_NN_DIGITS], ci, t[MAX_NN_DIGITS]; 00608 int8_t i; 00609 uint8_t ciBits, j, s; 00610 00611 /* Store b, b^2 mod d, and b^3 mod d. 00612 */ 00613 Assign (bPower[0], b, dDigits); 00614 ModMult (bPower[1], bPower[0], b, d, dDigits); 00615 ModMult (bPower[2], bPower[1], b, d, dDigits); 00616 00617 ASSIGN_DIGIT (t, 1, dDigits); 00618 00619 cDigits = Digits (c, cDigits); 00620 for (i = cDigits - 1; i >= 0; i--) { 00621 ci = c[i]; 00622 ciBits = NN_DIGIT_BITS; 00623 00624 /* Scan past leading zero bits of most significant digit. 00625 */ 00626 if (i == (int8_t)(cDigits - 1)) { 00627 while (! DIGIT_2MSB (ci)) { 00628 ci <<= 2; 00629 ciBits -= 2; 00630 } 00631 } 00632 00633 for (j = 0; j < ciBits; j += 2, ci <<= 2) { 00634 /* Compute t = t^4 * b^s mod d, where s = two MSB's of ci. 00635 */ 00636 ModMult (t, t, t, d, dDigits); 00637 ModMult (t, t, t, d, dDigits); 00638 if ((s = DIGIT_2MSB (ci)) != 0) 00639 ModMult (t, t, bPower[s-1], d, dDigits); 00640 } 00641 } 00642 00643 Assign (a, t, dDigits); 00644 } 00645 00646 //Computes a = b * c mod d, d is generalized mersenne prime, d = 2^KEYBITS - omega 00647 void ModMultOpt(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * c, NN_DIGIT * d, NN_DIGIT * omega, NN_UINT digits) 00648 { 00649 ModMult (a, b, c, d, digits); 00650 } 00651 00652 //Computes a = b^2 mod d, The Standard Squaring Algorithm in "High-Speed RSA Implementation" 00653 void ModSqr(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * d, NN_UINT digits) 00654 { 00655 NN_DIGIT t[2*MAX_NN_DIGITS]; 00656 Sqr (t, b, digits); 00657 Mod (a, t, 2 * digits, d, digits); 00658 } 00659 00660 void ModSqrOpt(NN_DIGIT * a, NN_DIGIT * b, NN_DIGIT * d, NN_DIGIT * omega, NN_UINT digits) 00661 { 00662 NN_DIGIT t[2*MAX_NN_DIGITS]; 00663 int8_t bDigits; 00664 00665 bDigits = Digits (b, digits); 00666 if (bDigits < MAX_NN_DIGITS) 00667 AssignZero(t+2*bDigits, 2*MAX_NN_DIGITS-2*bDigits); 00668 Sqr (t, b, digits); 00669 Mod (a, t, 2 * digits, d, digits); 00670 } 00671 00672 /* Compute a = 1/b mod c, assuming inverse exists. 00673 a, b, c can be same 00674 Lengths: a[digits], b[digits], c[digits]. 00675 Assumes gcd (b, c) = 1, digits < MAX_NN_DIGITS. 00676 */ 00677 void ModInv (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits) 00678 { 00679 NN_DIGIT q[MAX_NN_DIGITS], t1[MAX_NN_DIGITS], t3[MAX_NN_DIGITS], 00680 u1[MAX_NN_DIGITS], u3[MAX_NN_DIGITS], v1[MAX_NN_DIGITS], 00681 v3[MAX_NN_DIGITS], w[2*MAX_NN_DIGITS]; 00682 int8_t u1Sign; 00683 00684 /* Apply extended Euclidean algorithm, modified to avoid negative 00685 numbers. 00686 */ 00687 ASSIGN_DIGIT (u1, 1, digits); 00688 AssignZero (v1, digits); 00689 Assign (u3, b, digits); 00690 Assign (v3, c, digits); 00691 u1Sign = 1; 00692 00693 while (! Zero (v3, digits)) { 00694 Div (q, t3, u3, digits, v3, digits); 00695 Mult (w, q, v1, digits); 00696 Add (t1, u1, w, digits); 00697 Assign (u1, v1, digits); 00698 Assign (v1, t1, digits); 00699 Assign (u3, v3, digits); 00700 Assign (v3, t3, digits); 00701 u1Sign = -u1Sign; 00702 } 00703 00704 /* Negate result if sign is negative. 00705 */ 00706 if (u1Sign < 0) 00707 Sub (a, c, u1, digits); 00708 else 00709 Assign (a, u1, digits); 00710 } 00711 00712 /* 00713 * a= b/c mod d 00714 * algorithm in "From Euclid's GCD to Montgomery Multiplication to the Great Divide" 00715 */ 00716 void ModDivOpt (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_DIGIT *d, NN_UINT digits) 00717 { 00718 NN_DIGIT A[MAX_NN_DIGITS], B[MAX_NN_DIGITS], U[MAX_NN_DIGITS], V[MAX_NN_DIGITS]; 00719 int8_t tmp_even; 00720 00721 Assign(A, c, digits); 00722 Assign(B, d, digits); 00723 Assign(U, b, digits); 00724 AssignZero(V, digits); 00725 00726 while ((tmp_even = Cmp(A, B, digits)) != 0){ 00727 if (EVEN(A, digits)){ 00728 RShift(A, A, 1, digits); 00729 if (EVEN(U, digits)){ 00730 RShift(U, U, 1, digits); 00731 }else{ 00732 Add(U, U, d, digits); 00733 RShift(U, U, 1, digits); 00734 } 00735 }else if (EVEN(B, digits)){ 00736 RShift(B, B, 1, digits); 00737 if (EVEN(V, digits)){ 00738 RShift(V, V, 1, digits); 00739 }else{ 00740 Add(V, V, d, digits); 00741 RShift(V, V, 1, digits); 00742 } 00743 }else if (tmp_even > 0){ 00744 Sub(A, A, B, digits); 00745 RShift(A, A, 1, digits); 00746 if (Cmp(U, V, digits) < 0){ 00747 Add(U, U, d, digits); 00748 } 00749 Sub(U, U, V, digits); 00750 if (EVEN(U, digits)){ 00751 RShift(U, U, 1, digits); 00752 }else{ 00753 Add(U, U, d, digits); 00754 RShift(U, U, 1, digits); 00755 } 00756 }else{ 00757 Sub(B, B, A, digits); 00758 RShift(B, B, 1, digits); 00759 if (Cmp(V, U, digits) < 0){ 00760 Add(V, V, d, digits); 00761 } 00762 Sub(V, V, U, digits); 00763 if (EVEN(V, digits)){ 00764 RShift(V, V, 1, digits); 00765 }else{ 00766 Add(V, V, d, digits); 00767 RShift(V, V, 1, digits); 00768 } 00769 } 00770 } 00771 00772 Assign(a, U, digits); 00773 } 00774 00775 00776 //P1363 A.2.4 00777 void Lucas_Sequence(NN_DIGIT *V0, NN_DIGIT *Q0, NN_DIGIT *P, NN_DIGIT *Q, NN_DIGIT *k, NN_DIGIT *p, NN_DIGIT *omega) 00778 { 00779 NN_DIGIT v0[NUMWORDS], v1[NUMWORDS], q0[NUMWORDS], q1[NUMWORDS]; 00780 NN_DIGIT tmp[NUMWORDS]; 00781 int8_t r; 00782 00783 memset(v0, 0, NUMWORDS*NN_DIGIT_LEN); 00784 v0[0] = 2; 00785 memcpy(v1, P, NUMWORDS*NN_DIGIT_LEN); 00786 memset(q0, 0, NUMWORDS*NN_DIGIT_LEN); 00787 q0[0] = 1; 00788 memset(q1, 0, NUMWORDS*NN_DIGIT_LEN); 00789 q1[1] = 1; 00790 00791 r = Bits(k, NUMWORDS) - 1; 00792 00793 while(r >= 0) 00794 { 00795 ModMultOpt(q0, q0, q1, p, omega, NUMWORDS); 00796 if(b_testbit(k, r)){ 00797 ModMultOpt(q1, q0, Q, p, omega, NUMWORDS); 00798 ModMultOpt(tmp, P, q0, p, omega, NUMWORDS); 00799 ModMultOpt(v0, v0, v1, p, omega, NUMWORDS); 00800 ModSub(v0, v0, tmp, p, NUMWORDS); 00801 ModSqrOpt(v1, v1, p, omega, NUMWORDS); 00802 ModSub(v1, v1, q1, p, NUMWORDS); 00803 ModSub(v1, v1, q1, p, NUMWORDS); 00804 } 00805 else 00806 { 00807 memcpy(q1, q0, NUMWORDS*NN_DIGIT_LEN); 00808 ModMultOpt(v1, v1, v0, p, omega, NUMWORDS); 00809 ModMultOpt(tmp, P, q0, p, omega, NUMWORDS); 00810 ModSub(v1, v1, tmp, p, NUMWORDS); 00811 ModSqrOpt(v0, v0, p, omega, NUMWORDS); 00812 ModSub(v0, v0, q0, p, NUMWORDS); 00813 ModSub(v0, v0, q0, p, NUMWORDS); 00814 } 00815 } 00816 memcpy(V0, v0, NUMWORDS*NN_DIGIT_LEN); 00817 memcpy(Q0, q0, NUMWORDS*NN_DIGIT_LEN); 00818 } 00819 00820 //a = b^(1/2) mod c, from P1363 A.2.5 00821 int8_t ModSqrRootOpt(NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits, NN_DIGIT *omega) 00822 { 00823 NN_DIGIT m[NUMWORDS]; 00824 NN_DIGIT k[NUMWORDS], residue[NUMWORDS]; 00825 NN_DIGIT gam[NUMWORDS], i[NUMWORDS], twog[NUMWORDS]; 00826 00827 //case 1. 00828 memset(m, 0, NUMWORDS*NN_DIGIT_LEN); 00829 m[0] = 4; 00830 Div(k, residue, c, NUMWORDS, m, NUMWORDS); 00831 if (residue[0] == 3){ 00832 m[0] = 1; 00833 Add(k, k, m, NUMWORDS); 00834 ModExp(a, b, k, NUMWORDS, c, digits); 00835 return 1; 00836 } 00837 00838 //case 2. 00839 m[0] = 8; 00840 Div(k, residue, c, NUMWORDS, m, NUMWORDS); 00841 if(residue[0] == 5){ 00842 LShift(twog, b, 1, NUMWORDS); 00843 if(Cmp(twog, c, NUMWORDS) >=0) 00844 Sub(twog, twog, c, NUMWORDS); 00845 ModExp(gam, twog, k, NUMWORDS, c, digits); 00846 00847 ModSqr(i, gam, c, digits); 00848 ModMult(i, i, twog, c, digits); 00849 m[0] = 1; 00850 ModSub(i, i, m, c, digits); 00851 ModMult(a, b, gam, c, digits); 00852 ModMult(a, a, i, c, digits); 00853 return 1; 00854 } 00855 00856 //case 3. 00857 m[0] = 8; 00858 Div(k, residue, c, NUMWORDS, m, NUMWORDS); 00859 if(residue[0] == 1){ 00860 //Q = b 00861 00862 //0<P<p 00863 memset(i, 0, NUMWORDS*NN_DIGIT_LEN); 00864 i[0] = 1; 00865 m[0] = 1; 00866 //k = (p+1)/2 00867 memcpy(k, c, NUMWORDS*NN_DIGIT_LEN); 00868 Add(k, k, m, NUMWORDS); 00869 RShift(k, k, 1, NUMWORDS); 00870 00871 while (Cmp(i, c, NUMWORDS) < 0){ 00872 //compute V 00873 Lucas_Sequence(gam, twog, i, b, k, c, omega); //V = gam, Q = twog 00874 //z = V/2 mod p 00875 if ((gam[0] & 0x1) == 1) 00876 Add(gam, gam, c, NUMWORDS); 00877 RShift(gam, gam, 1, NUMWORDS); 00878 //check whether z^2 mod p = b 00879 ModSqrOpt(residue, gam, c, omega, NUMWORDS); 00880 if(Cmp(residue, b, NUMWORDS) == 0){ 00881 memcpy(a, gam, NUMWORDS*NN_DIGIT_LEN); 00882 return 1; 00883 } 00884 if(Cmp(twog, m, NUMWORDS) > 0){ 00885 Add(twog, twog, m, NUMWORDS); 00886 if(Cmp(twog, c, NUMWORDS) < 0) 00887 return -1; 00888 } 00889 Add(i, i, m, NUMWORDS); 00890 } 00891 } 00892 00893 return -1; 00894 } 00895 00896 /* Computes a = gcd(b, c). 00897 a, b, c can be same 00898 Lengths: a[digits], b[digits], c[digits]. 00899 Assumes b > c, digits < MAX_NN_DIGITS. 00900 */ 00901 void Gcd (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *c, NN_UINT digits) 00902 { 00903 NN_DIGIT t[MAX_NN_DIGITS], u[MAX_NN_DIGITS], v[MAX_NN_DIGITS]; 00904 00905 Assign (u, b, digits); 00906 Assign (v, c, digits); 00907 00908 while (! Zero (v, digits)) { 00909 Mod (t, u, digits, v, digits); 00910 Assign (u, v, digits); 00911 Assign (v, t, digits); 00912 } 00913 00914 Assign (a, u, digits); 00915 } 00916 00917 //-----------------------------------------------------------------------------------// 00918 00919 /* OTHER OPERATIONS */ 00920 00921 /* Returns sign of a - b. 00922 Lengths: a[digits], b[digits]. 00923 */ 00924 int8_t Cmp (NN_DIGIT *a, NN_DIGIT *b, NN_UINT digits) 00925 { 00926 int8_t i; 00927 00928 for (i = digits - 1; i >= 0; i--) { 00929 if (a[i] > b[i]) 00930 return (1); 00931 /* else added by Panos Kampankis*/ 00932 else if (a[i] < b[i]) 00933 return (-1); 00934 } 00935 00936 return (0); 00937 } 00938 00939 /* Returns nonzero iff a is zero. 00940 Lengths: a[digits]. 00941 */ 00942 int8_t Zero (NN_DIGIT *a, NN_UINT digits) 00943 { 00944 NN_UINT i; 00945 00946 for (i = 0; i < digits; i++) 00947 if (a[i]) 00948 return (0); 00949 00950 return (1); 00951 } 00952 00953 //returns 1 iff a = 1 00954 int8_t One(NN_DIGIT * a, NN_UINT digits) 00955 { 00956 uint8_t i; 00957 00958 for (i = 1; i < digits; i++) 00959 if (a[i]) 00960 return FALSE; 00961 if (a[0] == 1) 00962 return TRUE; 00963 00964 return FALSE; 00965 } 00966 00967 /* Returns the significant length of a in bits. 00968 Lengths: a[digits]. 00969 */ 00970 uint16_t Bits (NN_DIGIT *a, NN_UINT digits) 00971 { 00972 if ((digits = Digits (a, digits)) == 0) 00973 return (0); 00974 00975 return ((digits - 1) * NN_DIGIT_BITS + DigitBits (a[digits-1])); 00976 } 00977 00978 /* Returns the significant length of a in digits. 00979 Lengths: a[digits]. 00980 */ 00981 uint16_t Digits (NN_DIGIT *a, NN_UINT digits) 00982 { 00983 int8_t i; 00984 00985 for (i = digits - 1; i >= 0; i--) 00986 if (a[i]) 00987 break; 00988 00989 return (i + 1); 00990 } 00991 00992 // test whether the ith bit in a is one 00993 NN_DIGIT TestBit(NN_DIGIT * a, int16 i) 00994 { 00995 return (b_testbit(a,i)); 00996 } 00997 00998 //whether a is even or not 00999 int8_t Even(NN_DIGIT * a, NN_UINT digits) 01000 { 01001 return (((digits) == 0) || ! (a[0] & 1)); 01002 } 01003 01004 //whether a equals to b or not 01005 int8_t Equal(NN_DIGIT * a, NN_DIGIT * b, NN_UINT digits) 01006 { 01007 return (! Cmp (a, b, digits)); 01008 } 01009 01010 /* Computes a = b - c*d, where c is a digit. Returns borrow. 01011 a, b, d can be same 01012 Lengths: a[digits], b[digits], d[digits]. 01013 */ 01014 static NN_DIGIT SubDigitMult (NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT c, NN_DIGIT *d, NN_UINT digits) 01015 { 01016 NN_DIGIT borrow; 01017 uint16_t i; 01018 NN_DOUBLE_DIGIT t; 01019 01020 if (c == 0) 01021 return (0); 01022 borrow = 0; 01023 for (i = 0; i < digits; i++) { 01024 t = DigitMult (c, d[i]); 01025 if ((a[i] = b[i] - borrow) > (MAX_NN_DIGIT - borrow)) 01026 borrow = 1; 01027 else 01028 borrow = 0; 01029 if ((a[i] -= (t & MAX_NN_DIGIT)) > (MAX_NN_DIGIT - (t & MAX_NN_DIGIT))) 01030 borrow++; 01031 borrow += (NN_DIGIT)(t >> NN_DIGIT_BITS); 01032 } 01033 return (borrow); 01034 } 01035 01036 /* Returns the significant length of a in bits, where a is a digit. 01037 */ 01038 static uint16_t DigitBits (NN_DIGIT a) 01039 { 01040 uint16_t i; 01041 01042 for (i = 0; i < NN_DIGIT_BITS; i++, a >>= 1) 01043 if (a == 0) 01044 break; 01045 01046 return (i); 01047 } 01048 01049 /* Sets a = b / c, where a and c are digits. 01050 Lengths: b[2]. 01051 Assumes b[1] < c and HIGH_HALF (c) > 0. For efficiency, c should be 01052 normalized. 01053 from digit.c 01054 */ 01055 void DigitDiv (NN_DIGIT *a, NN_DIGIT b[2], NN_DIGIT c) 01056 { 01057 NN_DOUBLE_DIGIT t; 01058 01059 t = (((NN_DOUBLE_DIGIT)b[1]) << NN_DIGIT_BITS) ^ ((NN_DOUBLE_DIGIT)b[0]); 01060 01061 *a = t/c; 01062 } 01063 01064 NN_UINT omega_mul(NN_DIGIT *a, NN_DIGIT *b, NN_DIGIT *omega, NN_UINT digits) 01065 { 01066 01067 Assign(a, b, digits); 01068 a[digits+3] += AddDigitMult(&a[3], &a[3], omega[3], b, digits); 01069 return (digits+4); 01070 } 01071 }; 01072 01073 } //end of namespace wiselib 01074 01075 #endif //end