Wiselib
wiselib.testing/algorithms/crypto/pmp.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines