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_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, ¶ms.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(¶ms.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