Wiselib
wiselib.testing/algorithms/crypto/eccf2m.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_ECC_H
00021 #define  __ALGORITHMS_CRYPTO_ECC_H
00022 
00023 #include <string.h>
00024 
00025 // number of bits in key
00026 #define NUMBITS 163
00027 #define NUMWORDS (42)
00028 
00029 namespace wiselib
00030 {
00031 //----------------------------STRUCTS DEFINITIONS-----------------------//
00032 
00033       // a finite field element from GF(2)[p], modulo some irreducible
00034       // polynomial, represented with a polynomial basis as
00035       // b_{p-1} x^{p-1} + b_{p-2} x^{p-2} + ... + b_1 x^1 + b_0
00036       struct Elt
00037       {
00038          // b_{p-1} o b_{p-2} o ... o b_1 o b_0;
00039          // words are stored as big endian, so b_{p-1} \in val[0] and
00040          // b_0 \in val[NUMWORDS-1]
00041          uint8_t val[NUMWORDS];
00042       };
00043       typedef struct Elt Elt;
00044 
00045 
00046       // a curve over GF(2)[p] of the form
00047       // y^2 + x y = x^3 + a_4 x^2 + a_6
00048       struct Curve
00049       {
00050          // curve's coefficients
00051          Elt a4;
00052          Elt a6;
00053 
00054          // modulus for points on the curve
00055          uint8_t modulus[NUMWORDS];
00056 
00057          // number of bits necessary to represent modulus
00058          uint8_t bitlength;
00059       };
00060       typedef struct Curve Curve;
00061 
00062       // a point, (x,y), on a curve
00063       struct Point
00064       {
00065          // point's coordinates
00066          Elt x;
00067          Elt y;
00068       };
00069       typedef struct Point Point;
00070 
00071       // parameters for ECC
00072       struct Params
00073       {
00074          // curve over which ECC will be performed
00075          Curve E;
00076 
00077          // a point on E of order r
00078          Point G;
00079 
00080          // a positive, prime integer dividing the number of points on E
00081          uint8_t r[NUMWORDS];
00082 
00083          // a positive prime integer, s.t. k = #E/r
00084          uint8_t k[NUMWORDS];
00085 
00086          // field shall be GF(2)[p]
00087          uint16_t p;
00088 
00089          // coefficients for irreducible pentanomial,
00090          // x^m + x^k3 + x^k2 + x^k1 + 1
00091          uint8_t pentanomial_k1;
00092          uint8_t pentanomial_k2;
00093          uint8_t pentanomial_k3;
00094       };
00095       typedef struct Params Params;
00096 
00097       // private key for ECC
00098       struct PrivKey
00099       {
00100          // the secret
00101          uint8_t s[NUMWORDS];
00102       };
00103       typedef struct PrivKey PrivKey;
00104 
00105       // public key for ECC
00106       struct PubKey
00107       {
00108          // the point
00109          Point W;
00110       };
00111       typedef struct PubKey PubKey;
00112 
00113       // block of data
00114       struct DataBlock
00115       {
00116          // the point
00117          uint8_t d[NUMWORDS];
00118       };
00119       typedef struct DataBlock DataBlock;
00120 
00121       static Params params;
00122       typedef int16_t index_t;
00123 
00124       // a type for the mote's 8-bit words
00125       typedef uint8_t word_t;
00126 
00127       // a type for a mote's state
00128       typedef uint8_t state_t;
00129 
00130 //----------------------------END OF STRUCTS-----------------------//
00131 
00141 class ECC{
00142 public:
00143 
00144 //----------------------bint routines-----------------------------//
00145          static inline void b_clear(uint8_t * a)
00146          {
00147             for (int16_t i = 0; i < NUMWORDS; i++)
00148             {
00149                *(a+i)=0;
00150             }
00151             //memset(a, 0, NUMWORDS);
00152          }
00153    
00154          //Sets ith bit (where least significant bit is 0th bit) of bint.
00155          static inline void b_setbit(uint8_t * a, index_t i)
00156          {
00157             *(a + NUMWORDS - (i / 8) - 1) |= (1 << (i % 8));
00158          }
00159 
00160          //Clears ith bit (where least significant bit is 0th bit) of bint.
00161          static inline void b_clearbit(uint8_t * a, index_t i)
00162          {
00163             *(a + NUMWORDS - (i / 8) - 1) &= (0xffff ^ (1 << (i % 8)));
00164          }
00165 
00166          //returns true if bint is zero.
00167          static inline bool b_iszero(uint8_t * a)
00168          {
00169             // index for loop
00170             index_t i;
00171 
00172             // determine whether bint is 0; loop ignores top half of a[],
00173             // so it'd better be modulo dp.E.modulus already;
00174             // casting effectively unrolls loop a bit, saving us some cycles
00175             for (i = 0 + NUMWORDS/2, a = a + NUMWORDS - 2; i < NUMWORDS; i++, a-=2)
00176                if (*((uint16_t *) a))
00177                   return false;
00178 
00179             return true;
00180          }
00181    
00182          //a=b
00183          static inline void b_copy(uint8_t * a, uint8_t * b)
00184          {
00185             // index for loop
00186             index_t i;
00187 
00188             // copy a[] into b[]; casting effectively unrolls loop a bit,
00189             // saving us some cycles
00190             for (i = 0; i < NUMWORDS; i += 2)
00191                *((uint16_t *) (b + i)) = *((uint16_t *) (a + i));
00192          }
00193 
00194          //c= a + b (storing the result in a uint16 variable for checking if overflow happens)
00195          static inline void b_add(uint8_t * a,uint8_t * b, uint8_t *c)
00196          {
00197             int8_t k;
00198             uint8_t carry=0;
00199 
00200             for(k = NUMWORDS - 1; k > -1 ;k--)
00201             {
00202 
00203                uint16_t med=0;
00204                *(c + k)= *(a + k) + *(b + k) + carry;
00205                med = *(a + k) + *(b + k) + carry;
00206 
00207                //check for overflow
00208                if((med & 0xff00 ) == 0)
00209                {
00210                   carry=0;
00211                }
00212                else
00213                {
00214                   carry=1;
00215                }
00216             }
00217          }
00218 
00219          //c= a * b
00220          static inline void b_mul(uint8_t * a, uint8_t * b, uint8_t * c)
00221          {
00222             // index variable
00223             index_t i;
00224             uint8_t temp[NUMWORDS];
00225             uint8_t temp2[NUMWORDS];
00226 
00227             // clear bints
00228             b_clear(c);
00229             b_clear(temp2);
00230             b_clear(temp);
00231 
00232             // perform multiplication
00233             for (i = b_bitlength(a)-1; i >= 0; i--)
00234             {
00235 
00236                b_add(c, c, temp);
00237                if (b_testbit(a, i))
00238                {
00239                   b_add(temp, b, temp2);
00240                   b_copy(temp2,c);
00241                }
00242                else
00243                {
00244                   b_copy(temp,c);
00245                }
00246             }
00247          }
00248 
00249          //c= a XOR b
00250          static inline void b_xor(uint8_t * a, uint8_t * b, uint8_t * c)
00251          {
00252             // index for loop
00253             index_t i;
00254 
00255             // let c[] = a[] XOR b[]; casting effectively unrolls loop a bit,
00256             // saving us some cycles
00257             for (i = 0; i < NUMWORDS; i += 2, a += 2, b += 2, c += 2)
00258                *((uint16_t *) c) = *((uint16_t *) a) ^ *((uint16_t *) b);
00259          }
00260 
00261          //Returns -1 if a < b, 0 if a == b, and 1 if a > b.
00262          static inline int8_t b_compareto(uint8_t * a, uint8_t * b)
00263          {
00264 
00265             // index for loop
00266             uint8_t lth = NUMWORDS;
00267 
00268             // iterate over a[] and b[], looking for a difference
00269             while (lth && *a == *b)
00270             {
00271                a++;
00272                b++;
00273                lth--;
00274             }
00275 
00276             // if we reached end of a[] and b[], they're the same
00277             if (!lth)
00278                return 0;
00279 
00280             // if the current byte in a[] is greater than that in b[],
00281             // a[] is bigger than b[]
00282             else if (*a > *b)
00283                return 1;
00284 
00285             // else b[] is bigger than a[]
00286             else
00287                return -1;
00288          }
00289    
00290          //Shifts bint left by n bits, storing result in b.
00291          static inline void b_shiftleft(uint8_t * a, index_t n, uint8_t * b)
00292          {
00293             // index variable
00294             index_t i;
00295 
00296             // storage for shift's magnitudes
00297             index_t bytes, bits;
00298 
00299             // determine how far to shift whole bytes
00300             bytes = n / 8;
00301 
00302             // determine how far to shift bits within bytes or across
00303             // pairs of bytes
00304             bits = n % 8;
00305 
00306             // shift whole bytes as appropriate
00307             if (bytes > 0)
00308             {
00309                for (i = bytes; i < NUMWORDS; i++)
00310                   *(b + i-bytes) = *(a + i);
00311                for (i = NUMWORDS - bytes; i < NUMWORDS; i++)
00312                   *(b + i) = (word_t) 0x00;
00313             }
00314 
00315             // else prepare just to shift bits
00316             else if (bytes == 0)
00317                b_copy(a, b);
00318 
00319             // shift bits as appropriate
00320             for (i = 1; i < NUMWORDS; i++)
00321                *(b + i - 1) = (*(b + i-1) << bits) | (*(b + i) >> (8 - bits));
00322             *(b + NUMWORDS-1) = (*(b + NUMWORDS-1) << bits);
00323          }
00324 
00325          //Shifts bint left by 1 bit.  Though a call to this
00326          //function is functionally equivalent to one to b_shiftleft(a, 1, b),
00327          //this version is meant to optimize a common case (shifts by 1).
00328          static inline void b_shiftleft1(uint8_t * a, uint8_t * b)
00329          {
00330             // index variable
00331             index_t i;
00332 
00333             if (a != b)
00334                b_copy(a, b);
00335 
00336             // shift bits as appropriate; loop is manually unrolled a bit
00337             // to save some cycles
00338             for (i = 1; i < NUMWORDS - 1; i++)
00339             {
00340                *(b + i-1) <<= 1;
00341                if (*(b + i) & 0x0080)
00342                   *(b+ i-1) |= 0x0001;
00343                i++;
00344                *(b + i-1) <<= 1;
00345                if (*(b + i) & 0x0080)
00346                   *(b+ i-1) |= 0x0001;
00347             }
00348             *(b + NUMWORDS-2) <<= 1;
00349             if (*(b + NUMWORDS-1) & 0x0080)
00350                *(b + NUMWORDS-2) |= 0x0001;
00351             *(b + NUMWORDS-1) <<= 1;
00352          }
00353    
00354          //Shifts bint left by 2 bits.
00355          static inline void b_shiftleft2(uint8_t * a, uint8_t * b)
00356          {
00357             // index variable
00358             index_t i;
00359 
00360             if (a != b)
00361                b_copy(a, b);
00362 
00363 
00364             // shift bits as appropriate
00365             for (i = 1; i < NUMWORDS; i++)
00366             {
00367                *(b + i-1) <<= 2;
00368                if (*(b + i) & 0x0040)
00369                   *(b+ i-1) |= 0x0001;
00370                if (*(b + i) & 0x0080)
00371                   *(b+ i-1) |= 0x0002;
00372             }
00373             *(b + NUMWORDS-1) <<= 2;
00374          }
00375 
00376          //Returns the number of bits in the shortest possible representation of this bint.
00377          static inline index_t b_bitlength(uint8_t * a)
00378          {
00379             // index variables;
00380             index_t i;
00381 
00382             // local storage
00383             uint8_t n, x, y;
00384 
00385             // iterate over other bytes, looking for most significant set bit;
00386             // algorithm from Henry S. Warren Jr., Hacker's Delight
00387             for (i = 0; i < NUMWORDS; i++)
00388             {
00389                x = *(a+i);
00390                if (x)
00391                {
00392                   n = 8;
00393                   y = x >> 4;
00394                   if (y != 0) {n = n - 4; x = y;}
00395                   y = x >> 2;
00396                   if (y != 0) {n = n - 2; x = y;}
00397                   y = x >> 1;
00398                   if (y != 0)
00399                      return (NUMWORDS - i - 1) * 8 + (8 - (n - 2));
00400 
00401                   return (NUMWORDS - i - 1) * 8 + (8 - (n - x));
00402                }
00403             }
00404 
00405             // if no bits are set, bint is 0
00406             return 0;
00407          }
00408 
00409          //test if bit i-th bit of bint is set
00410          static inline bool b_testbit(uint8_t * a, index_t i)
00411          {
00412             return (*(a + NUMWORDS - (i / 8) - 1) & (1 << (i % 8)));
00413          }
00414 
00415          //Returns TRUE iff bints are equal.
00416          static inline bool b_isequal(uint8_t * a, uint8_t * b)
00417          {
00418             // index variable
00419             index_t i;
00420 
00421             // iterate over bints, looking for a difference
00422             for (i = 0; i < NUMWORDS; i++)
00423                if (*(a + NUMWORDS - 1 - i) != *(b + NUMWORDS - 1 - i))
00424                   return false;
00425 
00426             // if no difference found, bints are equal
00427             return true;
00428          }
00429 
00430          //Subtracts one string of unsigned bytes from another.
00431          static inline void b_sub(uint8_t *fromp, uint8_t *subp, int16_t lth)
00432          {
00433             // local variables
00434             uint8_t *cp, tmp;
00435 
00436             /* step 1 */
00437             for (subp += lth - 1, fromp += lth - 1 ; lth--; subp--, fromp--)
00438             {
00439                tmp = *fromp;
00440                *fromp -= *subp;
00441 
00442                /* have to borrow */
00443                if (*fromp > tmp)
00444                {
00445                   cp = fromp;
00446                   do
00447                   {
00448                      cp--;
00449                      (*cp)--;
00450                   }
00451                   while(*cp == 0xff);
00452                }
00453             }
00454          }
00455 
00456          //remodularizes by using long division.
00457          static inline void b_mod(uint8_t * remp, uint8_t * modp, int16_t lth)
00458          {
00459             uint8_t *chremp,    /* ptr to current MSB of remainder */
00460             *rtp, *mtp, /* tmp pointers for comparing */
00461             *dtp,       /* ptr for dividing */
00462             tdiv[2];
00463             uint16_t tmp, quot;
00464             int16_t tlth;       /* counter for main loop */
00465             uint8_t j;
00466             uint8_t trials[16];
00467             uint8_t subprod[1 + 96];
00468 
00469             //memset(trials, 0, 16);
00470             for(int16_t i=0;i<16;i++)
00471             {
00472                trials[i]=0;
00473             }
00474 
00475             modp += NUMWORDS / 2;
00476             *trials = *modp >> 1;
00477             *(trials + 1) = *modp << 7;
00478             /* step 1 */
00479             while (b_compareto(remp, modp) > 0) b_sub(remp, modp, lth);
00480             /* step 2 */
00481             for (chremp = remp, tlth = lth; tlth--; chremp++)
00482             {
00483                /* step 3 */
00484                *tdiv = *chremp;
00485                *(tdiv + 1) = *(chremp + 1);
00486 
00487                for (j = 8, dtp = trials, quot = 0; j--; dtp += 2)
00488                {
00489                   quot <<= 1;
00490                   if (*tdiv > *dtp || (*tdiv == *dtp &&
00491                         *(tdiv + 1) >= *(dtp + 1)))
00492                   {
00493                      b_sub(tdiv, dtp, 2);
00494                      quot++;
00495                   }
00496                }
00497                /* step 4 */
00498                while (quot > 0xFF) quot = 0xFF;
00499                *tdiv = quot - ((quot)? 1: 0);
00500                /* step 5 */
00501                if (*tdiv)
00502                {
00503                   //memset(subprod, 0, lth + 1);
00504                   for(int16_t i=0;i<lth+1;i++)
00505                   {
00506                      subprod[i]=0;
00507                   }
00508 
00509                   for (mtp = &modp[lth - 1], rtp = &subprod[lth], j = lth; j--;
00510                         mtp--)
00511                   {
00512                      tmp = *mtp * *tdiv;
00513                      tmp += *rtp;
00514                      *rtp-- = tmp & 0xFF;
00515                      *rtp = (tmp >> 8);
00516                   }
00517                   while (b_compareto(subprod, chremp) > 0)
00518                   {
00519                      b_sub(&subprod[1], modp, lth);
00520                   }
00521                   b_sub(chremp, subprod, lth + 1);
00522                }
00523                /* step 6 */
00524                while(*chremp || b_compareto(&chremp[1], modp) > 0)
00525                   b_sub(&chremp[1], modp, lth);
00526             }
00527          }
00528 //----------------------end of bint routines-----------------------------//
00529 
00530 //-------------------------POINT ROUTINES-------------------------------//
00531    
00532          //clears a point.
00533          static inline void p_clear(Point * P0)
00534          {
00535             // clear each ordinate
00536             b_clear(P0->x.val);
00537             b_clear(P0->y.val);
00538          }
00539 
00540          //Returns TRUE iff P0 == (0,0).
00541          static inline bool p_iszero(Point * P0)
00542          {
00543             return (b_iszero(P0->x.val) && b_iszero(P0->y.val));
00544          }
00545 
00546          //P1=P0
00547          static inline void p_copy(Point * P0, Point * P1)
00548          {
00549             // copy point's ordinates
00550             b_copy(P0->x.val, P1->x.val);
00551             b_copy(P0->y.val, P1->y.val);
00552          }
00553 
00554          //returns true if Points P0 and P1 are equal
00555          static inline bool p_isequal(Point * P0, Point * P1)
00556          {
00557             //check if x coordinates and y coordinates are equal
00558             if(b_isequal(P0->x.val,P1->x.val) && b_isequal(P0->y.val,P1->y.val))
00559                return true;
00560             else
00561                return false;
00562          }
00563 
00564 //-------------------------END OF POINT ROUTINES----------------------------//
00565 
00566 //------------------------------FIELD ROUTINES----------------------------//
00567    
00568          // b = a (mod modulus).
00569          // a and b are allowed to point to the same memory.
00570          // Hardcoded at present with default curve's parameters to save cycles.
00571          static void f_mod(uint8_t * a, uint8_t * b)
00572          {
00573             // local variables
00574             index_t blr, shf;
00575             int8_t comp;
00576             uint8_t r[NUMWORDS];
00577 
00578             // clear bint
00579             b_clear(r);
00580 
00581             // modular reduction
00582             comp = b_compareto(a, params.E.modulus);
00583             if (comp < 0)
00584             {
00585                b_copy(a, b);
00586                return;
00587             }
00588             else if (comp == 0)
00589             {
00590                b_copy(r, b);
00591                return;
00592             }
00593             b_copy(a, r);
00594             while ((blr = b_bitlength(r)) >= params.E.bitlength)
00595             {
00596                shf = blr - params.E.bitlength;
00597                *(r + NUMWORDS - ((163+shf) / 8) - 1) ^= (1 << ((163+shf) % 8));
00598                *(r + NUMWORDS - ((7+shf) / 8) - 1) ^= (1 << ((7+shf) % 8));
00599                *(r + NUMWORDS - ((6+shf) / 8) - 1) ^= (1 << ((6+shf) % 8));
00600                *(r + NUMWORDS - ((3+shf) / 8) - 1) ^= (1 << ((3+shf) % 8));
00601                *(r + NUMWORDS - ((0+shf) / 8) - 1) ^= (1 << ((0+shf) % 8));
00602             }
00603             b_copy(r, b);
00604          }
00605 
00606          // c = a + b.
00607          static inline void f_add(uint8_t * a, uint8_t * b, uint8_t * c)
00608          {
00609             b_xor(a, b, c);
00610          }
00611 
00612          //c = ab mod f
00613          //Algorithm 4 from High-Speed Software Multiplication in F_{2^m}.
00614          //a, b, and/or c are allowed to point to the same memory.
00615          static inline void f_mul(uint8_t * a, uint8_t * b, uint8_t * c)
00616          {
00617             // local variables
00618             index_t i, j, k;
00619             uint8_t T[NUMWORDS];
00620 
00621             // perform multiplication
00622             for (i = 0; i < NUMWORDS; i++)
00623                *(T+i) = 0x00;
00624             for (j = 7; j >= 0; j--)
00625             {
00626                for (i = 0; i <= NUMWORDS/2-1; i++)
00627                   if (b_testbit(a, i*8+j))
00628                      for (k = 0; k <= NUMWORDS/2-1; k++)
00629                         *(T+(NUMWORDS-1)-(k+i)) ^= *(b+(NUMWORDS-1)-k);
00630                if (j != 0) b_shiftleft1(T, T);
00631             }
00632 
00633             // modular reduction
00634             f_mod(T, c);
00635 
00636          }
00637 
00638          // d = a^-1.
00639          //Algorithm 8 in "Software Implementation of Elliptic Curve Cryptography
00640          //Over Binary Fields", D. Hankerson, J.L. Hernandez, A. Menezes.
00641          //a and d are allowed to point to the same memory.
00642          static inline void f_inv(uint8_t * a, uint8_t * d)
00643          {
00644             // local variables
00645             index_t i;
00646             int8_t j;
00647             uint8_t * ptr;
00648             uint8_t anonymous[NUMWORDS*5];
00649             uint8_t * b = anonymous + NUMWORDS;
00650             uint8_t * c = b + NUMWORDS;
00651             uint8_t * u = c + NUMWORDS;
00652             uint8_t * v = u + NUMWORDS;
00653 
00654             // 1.  b <-- 1, c <-- 1, u <-- a, v <-- f
00655             for (i = 0; i < NUMWORDS; i++)
00656             {
00657                *(b+i) = 0x00;
00658                *(c+i) = 0x00;
00659                *(v+i) = *(params.E.modulus+i);
00660             }
00661             *(b+NUMWORDS-1) = 0x01;
00662             f_mod(a, u);
00663 
00664             // 2.  While deg(u) != 0
00665             while (b_bitlength(u) > 1)
00666             {
00667                // 2.1  j <-- deg(u) - deg(v).
00668                j = (b_bitlength(u) - 1) - (b_bitlength(v) - 1);
00669 
00670                // 2.2  If j < 0 then:
00671                if (j < 0)
00672                {
00673                   // u <--> v
00674                   ptr = u;
00675                   u = v;
00676                   v = ptr;
00677 
00678                   // b <--> c
00679                   ptr = b;
00680                   b = c;
00681                   c = ptr;
00682 
00683                   // j <-- -j
00684                   j = -j;
00685                }
00686 
00687                // 2.3  u <-- u + x^jv
00688                switch (j)
00689                {
00690                case 0:
00691                   f_add(u, v, u);
00692                   f_add(b, c, b);
00693                   break;
00694                case 1:
00695                   b_shiftleft1(v, anonymous);
00696                   f_add(u, anonymous, u);
00697                   b_shiftleft1(c, anonymous);
00698                   f_add(b, anonymous, b);
00699                   break;
00700                case 2:
00701                   b_shiftleft2(v, anonymous);
00702                   f_add(u, anonymous, u);
00703                   b_shiftleft2(c, anonymous);
00704                   f_add(b, anonymous, b);
00705                   break;
00706                default:
00707                   b_shiftleft(v, j, anonymous);
00708                   f_add(u, anonymous, u);
00709                   b_shiftleft(c, j, anonymous);
00710                   f_add(b, anonymous, b);
00711                   break;
00712                }
00713             }
00714             b_copy(b, d);
00715          }
00716 //----------------------------END OF FIELD ROUTINES------------------------//
00717 
00718    
00719 //-----------------------------CURVE ROUTINES------------------------------//
00720    
00721          //Q=P1 + P2.
00722          //Algorithm 7 in An Overview of Elliptic Curve Cryptography, Lopez and Dahab.
00723          static inline void c_add(Point * P1, Point * P2, Point * Q)
00724          {
00725             uint8_t lambda[NUMWORDS], numerator[NUMWORDS];
00726             Point T;
00727 
00728             // 1.  if P1 = 0
00729             if (p_iszero(P1))
00730             {
00731                // Q <-- P2
00732                p_copy(P2, Q);
00733                return;
00734             }
00735 
00736             // 2.  if P2 = 0
00737             if (p_iszero(P2))
00738             {
00739                // Q <-- P1
00740                p_copy(P1, Q);
00741                return;
00742             }
00743 
00744             // 3.  if x1 = x2
00745             if (b_isequal(P1->x.val, P2->x.val))
00746             {
00747                // if y1 = y2
00748                if (b_isequal(P1->y.val, P2->y.val))
00749                {
00750                   // lambda = x1 + y1/x1
00751                   f_inv(P1->x.val, lambda);
00752                   f_mul(lambda, P1->y.val, lambda);
00753                   f_add(lambda, P1->x.val, lambda);
00754 
00755                   // x3 = lambda^2 + lambda + a
00756                   f_mul(lambda, lambda, T.x.val);
00757                   f_add(T.x.val, lambda, T.x.val);
00758                   f_add(T.x.val, params.E.a4.val, T.x.val);
00759                }
00760                else
00761                {
00762                   // Q <-- 0
00763                   b_clear(T.x.val);
00764                   b_clear(T.y.val);
00765                }
00766             }
00767             else
00768             {
00769                // lambda <-- (y2 + y1)/(x2 + x1)
00770                f_add(P2->y.val, P1->y.val, numerator);
00771                f_add(P2->x.val, P1->x.val, lambda);
00772                f_inv(lambda, lambda);
00773                f_mul(numerator, lambda, lambda);
00774 
00775                // x3 <-- lambda^2 + lambda + x1 + x2 + a
00776                f_mul(lambda, lambda, T.x.val);
00777                f_add(T.x.val, lambda, T.x.val);
00778                f_add(T.x.val, P1->x.val, T.x.val);
00779                f_add(T.x.val, P2->x.val, T.x.val);
00780                f_add(T.x.val, params.E.a4.val, T.x.val);
00781             }
00782 
00783             // y3 <-- lambda(x1 + x2) + x3 + y1
00784             f_add(P1->x.val, T.x.val, T.y.val);
00785             f_mul(T.y.val, lambda, T.y.val);
00786             f_add(T.y.val, T.x.val, T.y.val);
00787             f_add(T.y.val, P1->y.val, T.y.val);
00788 
00789             // return
00790             p_copy(&T, Q);
00791          }
00792 
00793          //Multiplication of P0 by n-> results in P1.
00794          //Based on Algorithm IV.1 on p. 63 of "Elliptic Curves in Cryptography"
00795          // by I. F. Blake, G. Seroussi, N. P. Smart.
00796          static inline void c_mul(uint8_t * n, Point * P0, Point * P1)
00797          {
00798             // index variable
00799             index_t i;
00800 
00801             // clear point
00802             p_clear(P1);
00803 
00804             // perform multiplication
00805             for (i = b_bitlength(n) - 1; i >= 0; i--)
00806             {
00807                c_add(P1, P1, P1);
00808                if (b_testbit(n, i))
00809                   c_add(P1, P0, P1);
00810             }
00811          }
00812 //--------------------------END OF CURVE ROUTINES------------------------------//
00813    
00814 //----------------------------CRYPTO ROUTINEs-------------------------------//
00815    
00816 
00817          //generate a sensor nodes private key
00818          static inline uint8_t * gen_private_key(uint8_t * a,uint8_t b)
00819          {
00820             uint8_t d=1;
00821             for (uint8_t i = NUMWORDS/2; i < NUMWORDS; i++)
00822             {
00823                d = (d*i) + (234 - b);
00824                a[i] = (uint8_t) d; //rand()%256;
00825             }
00826             b_mod(a, params.r, NUMWORDS/2);
00827             return a;
00828          }
00829 
00830          //generate a sensor nodes public key
00831          static inline Point * gen_public_key(uint8_t * a,Point * P0)
00832          {
00833             c_mul(a, &params.G, P0);
00834             return P0;
00835          }
00836 
00837          //generate a shared secret between two sensor nodes
00838          static inline Point * gen_shared_secret(uint8_t * a,Point * P0, Point * P1)
00839          {
00840             c_mul(a, P0, P1);
00841             return P1;
00842          }
00843 
00844          static inline void init()
00845          {
00846             p_clear(&params.G);
00847             // initialize modulus
00848             params.p = 163;
00849             params.pentanomial_k3 = 7;
00850             params.pentanomial_k2 = 6;
00851             params.pentanomial_k1 = 3;
00852 
00853             b_clear(params.E.modulus);
00854 
00855             b_setbit(params.E.modulus, 163);
00856             b_setbit(params.E.modulus, 7);
00857             b_setbit(params.E.modulus, 6);
00858             b_setbit(params.E.modulus, 3);
00859             b_setbit(params.E.modulus, 0);
00860             params.E.bitlength = 164;
00861 
00862             // initialize curve
00863             b_clear(params.E.a4.val);
00864             params.E.a4.val[NUMWORDS - 1] = (word_t) 0x01;
00865             b_clear(params.E.a6.val);
00866             params.E.a6.val[NUMWORDS - 1] = (word_t) 0x01;
00867 
00868             // initialize r
00869             params.r[NUMWORDS - 21] = (word_t) 0x04;
00870             params.r[NUMWORDS - 20] = (word_t) 0x00;
00871             params.r[NUMWORDS - 19] = (word_t) 0x00;
00872             params.r[NUMWORDS - 18] = (word_t) 0x00;
00873             params.r[NUMWORDS - 17] = (word_t) 0x00;
00874             params.r[NUMWORDS - 16] = (word_t) 0x00;
00875             params.r[NUMWORDS - 15] = (word_t) 0x00;
00876             params.r[NUMWORDS - 14] = (word_t) 0x00;
00877             params.r[NUMWORDS - 13] = (word_t) 0x00;
00878             params.r[NUMWORDS - 12] = (word_t) 0x00;
00879             params.r[NUMWORDS - 11] = (word_t) 0x02;
00880             params.r[NUMWORDS - 10] = (word_t) 0x01;
00881             params.r[NUMWORDS - 9] = (word_t) 0x08;
00882             params.r[NUMWORDS - 8] = (word_t) 0xa2;
00883             params.r[NUMWORDS - 7] = (word_t) 0xe0;
00884             params.r[NUMWORDS - 6] = (word_t) 0xcc;
00885             params.r[NUMWORDS - 5] = (word_t) 0x0d;
00886             params.r[NUMWORDS - 4] = (word_t) 0x99;
00887             params.r[NUMWORDS - 3] = (word_t) 0xf8;
00888             params.r[NUMWORDS - 2] = (word_t) 0xa5;
00889             params.r[NUMWORDS - 1] = (word_t) 0xef;
00890 
00891             // initialize Gx
00892 
00893             params.G.x.val[NUMWORDS - 21] = (word_t) 0x02;
00894             params.G.x.val[NUMWORDS - 20] = (word_t) 0xfe;
00895             params.G.x.val[NUMWORDS - 19] = (word_t) 0x13;
00896             params.G.x.val[NUMWORDS - 18] = (word_t) 0xc0;
00897             params.G.x.val[NUMWORDS - 17] = (word_t) 0x53;
00898             params.G.x.val[NUMWORDS - 16] = (word_t) 0x7b;
00899             params.G.x.val[NUMWORDS - 15] = (word_t) 0xbc;
00900             params.G.x.val[NUMWORDS - 14] = (word_t) 0x11;
00901             params.G.x.val[NUMWORDS - 13] = (word_t) 0xac;
00902             params.G.x.val[NUMWORDS - 12] = (word_t) 0xaa;
00903             params.G.x.val[NUMWORDS - 11] = (word_t) 0x07;
00904             params.G.x.val[NUMWORDS - 10] = (word_t) 0xd7;
00905             params.G.x.val[NUMWORDS - 9] = (word_t) 0x93;
00906             params.G.x.val[NUMWORDS - 8] = (word_t) 0xde;
00907             params.G.x.val[NUMWORDS - 7] = (word_t) 0x4e;
00908             params.G.x.val[NUMWORDS - 6] = (word_t) 0x6d;
00909             params.G.x.val[NUMWORDS - 5] = (word_t) 0x5e;
00910             params.G.x.val[NUMWORDS - 4] = (word_t) 0x5c;
00911             params.G.x.val[NUMWORDS - 3] = (word_t) 0x94;
00912             params.G.x.val[NUMWORDS - 2] = (word_t) 0xee;
00913             params.G.x.val[NUMWORDS - 1] = (word_t) 0xe8;
00914 
00915             // initialize Gy
00916             params.G.y.val[NUMWORDS - 21] = (word_t) 0x02;
00917             params.G.y.val[NUMWORDS - 20] = (word_t) 0x89;
00918             params.G.y.val[NUMWORDS - 19] = (word_t) 0x07;
00919             params.G.y.val[NUMWORDS - 18] = (word_t) 0x0f;
00920             params.G.y.val[NUMWORDS - 17] = (word_t) 0xb0;
00921             params.G.y.val[NUMWORDS - 16] = (word_t) 0x5d;
00922             params.G.y.val[NUMWORDS - 15] = (word_t) 0x38;
00923             params.G.y.val[NUMWORDS - 14] = (word_t) 0xff;
00924             params.G.y.val[NUMWORDS - 13] = (word_t) 0x58;
00925             params.G.y.val[NUMWORDS - 12] = (word_t) 0x32;
00926             params.G.y.val[NUMWORDS - 11] = (word_t) 0x1f;
00927             params.G.y.val[NUMWORDS - 10] = (word_t) 0x2e;
00928             params.G.y.val[NUMWORDS - 9] = (word_t) 0x80;
00929             params.G.y.val[NUMWORDS - 8] = (word_t) 0x05;
00930             params.G.y.val[NUMWORDS - 7] = (word_t) 0x36;
00931             params.G.y.val[NUMWORDS - 6] = (word_t) 0xd5;
00932             params.G.y.val[NUMWORDS - 5] = (word_t) 0x38;
00933             params.G.y.val[NUMWORDS - 4] = (word_t) 0xcc;
00934             params.G.y.val[NUMWORDS - 3] = (word_t) 0xda;
00935             params.G.y.val[NUMWORDS - 2] = (word_t) 0xa3;
00936             params.G.y.val[NUMWORDS - 1] = (word_t) 0xd9;
00937 
00938             // initialize k
00939             b_clear(params.k);
00940             params.k[NUMWORDS - 1] = (word_t) 0x02;
00941 
00942          }
00943 //--------------------------END OF CRYPTO ROUTINEs-----------------------------//
00944 
00945 };
00946 
00947 } //end of namespace wiselib
00948 
00949 #endif // _ECC_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines