]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bigint/bigint.c
going to remove debug stuff ...
[avr-crypto-lib.git] / bigint / bigint.c
1 /* bigint.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2008  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 /**
20  * \file                bigint.c
21  * \author              Daniel Otte
22  * \date                2010-02-22
23  * 
24  * \license         GPLv3 or later
25  * 
26  */
27  
28
29 #include "bigint.h"
30 #include <string.h>
31
32 #include "bigint_io.h"
33 #include "cli.h"
34
35 #ifndef MAX
36  #define MAX(a,b) (((a)>(b))?(a):(b))
37 #endif
38
39 #ifndef MIN
40  #define MIN(a,b) (((a)<(b))?(a):(b))
41 #endif
42
43 #define SET_FBS(a, v) do{(a)->info &=0xF8; (a)->info |= (v);}while(0)
44 #define GET_FBS(a)   ((a)->info&BIGINT_FBS_MASK)
45 #define SET_NEG(a)   (a)->info |= BIGINT_NEG_MASK
46 #define SET_POS(a)   (a)->info &= ~BIGINT_NEG_MASK
47 #define XCHG(a,b)    do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
48 #define XCHG_PTR(a,b)    do{ a = (void*)(((uint16_t)(a)) ^ ((uint16_t)(b))); \
49                                  b = (void*)(((uint16_t)(a)) ^ ((uint16_t)(b))); \
50                                  a = (void*)(((uint16_t)(a)) ^ ((uint16_t)(b)));}while(0)
51
52 #define GET_SIGN(a) ((a)->info&BIGINT_NEG_MASK)
53
54 /******************************************************************************/
55 void bigint_adjust(bigint_t* a){
56         while(a->length_B!=0 && a->wordv[a->length_B-1]==0){
57                 a->length_B--;
58         }
59         if(a->length_B==0){
60                 a->info=0;
61                 return;
62         }
63         uint8_t t;
64         uint8_t i = 0x07;
65         t = a->wordv[a->length_B-1];
66         while((t&0x80)==0 && i){
67                 t<<=1;
68                 i--;
69         }
70         SET_FBS(a, i);
71 }
72
73 /******************************************************************************/
74
75 void bigint_copy(bigint_t* dest, const bigint_t* src){
76         memcpy(dest->wordv, src->wordv, src->length_B);
77         dest->length_B = src->length_B;
78         dest->info = src->info;
79 }
80
81 /******************************************************************************/
82
83 /* this should be implemented in assembly */
84 /*
85 void bigint_add_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
86         uint16_t t=0, i;
87         if(a->length_B < b->length_B){
88                 XCHG_PTR(a,b);
89         }
90         for(i=0; i<b->length_B; ++i){
91                 t = a->wordv[i] + b->wordv[i] + t;
92                 dest->wordv[i] = (uint8_t)t;
93                 t>>=8;
94         }
95         for(; i<a->length_B; ++i){
96                 t = a->wordv[i] + t;
97                 dest->wordv[i] = (uint8_t)t;
98                 t>>=8;
99         }
100         dest->wordv[i++] = t;
101         dest->length_B = i;
102         bigint_adjust(dest);
103 }
104 */
105 /******************************************************************************/
106
107 /* this should be implemented in assembly */
108 void bigint_add_scale_u(bigint_t* dest, const bigint_t* a, uint16_t scale){
109         uint16_t i,j=0;
110         uint16_t t=0;
111         if(scale>dest->length_B)
112                 memset(dest->wordv+dest->length_B, 0, scale-dest->length_B);
113         for(i=scale; i<a->length_B+scale; ++i,++j){
114                 t = a->wordv[j] + t;
115                 if(dest->length_B>i){
116                         t += dest->wordv[i];
117                 }
118                 dest->wordv[i] = (uint8_t)t;
119                 t>>=8;
120         }
121         while(t){
122                 if(dest->length_B>i){
123                         t = dest->wordv[i] + t;
124                 }
125                 dest->wordv[i] = (uint8_t)t;
126                 t>>=8;
127                 ++i;
128         }
129         if(dest->length_B < i){
130                 dest->length_B = i;
131         }
132         bigint_adjust(dest);
133 }
134
135 /******************************************************************************/
136
137 /* this should be implemented in assembly */
138 void bigint_sub_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
139         int8_t borrow=0;
140         int8_t  r;
141         int16_t t;
142         uint16_t i, min, max;
143         min = MIN(a->length_B, b->length_B);
144         max = MAX(a->length_B, b->length_B);
145         r = bigint_cmp_u(a,b);
146         if(r==0){
147                 dest->length_B = 0;
148                 dest->wordv[0] = 0;
149                 bigint_adjust(dest);
150                 return;
151         }
152         if(b->length_B==0){
153                 dest->length_B = a->length_B;
154                 memcpy(dest->wordv, a->wordv, a->length_B);
155                 dest->info = a->info;
156                 SET_POS(dest);
157                 return;
158         }
159         if(a->length_B==0){
160                         dest->length_B = b->length_B;
161                         memcpy(dest->wordv, b->wordv, b->length_B);
162                         dest->info = b->info;
163                         SET_NEG(dest);
164                         return;
165         }
166         if(r<0){
167                 bigint_sub_u(dest, b, a);
168                 SET_NEG(dest);
169         }else{
170                 for(i=0; i<min; ++i){
171                         t = a->wordv[i] - b->wordv[i] - borrow;
172                         if(t<0){
173                                 borrow = 1;
174                                 dest->wordv[i]=(uint8_t)t;
175                         }else{
176                                 borrow = 0;
177                                 dest->wordv[i]=(uint8_t)t;
178                         }
179                 }
180                 for(;i<max; ++i){
181                         t = a->wordv[i] - borrow;
182                         if(t<0){
183                                 borrow = 1;
184                                 dest->wordv[i]=(uint8_t)t;
185                         }else{
186                                 borrow = 0;
187                                 dest->wordv[i]=(uint8_t)t;
188                         }
189
190                 }
191                 SET_POS(dest);
192                 dest->length_B = i;
193                 bigint_adjust(dest);
194         }
195 }
196
197 /******************************************************************************/
198
199 int8_t bigint_cmp_u(const bigint_t* a, const bigint_t* b){
200         if(a->length_B > b->length_B){
201                 return 1;
202         }
203         if(a->length_B < b->length_B){
204                 return -1;
205         }
206         if(a->length_B==0){
207                 return 0;
208         }
209         uint16_t i;
210         i = a->length_B-1;
211         do{
212                 if(a->wordv[i]!=b->wordv[i]){
213                         if(a->wordv[i]>b->wordv[i]){
214                                 return 1;
215                         }else{
216                                 return -1;
217                         }
218                 }
219         }while(i--);
220         return 0;
221 }
222
223 /******************************************************************************/
224
225 void bigint_add_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
226         uint8_t s;
227         s  = GET_SIGN(a)?2:0;
228         s |= GET_SIGN(b)?1:0;
229         switch(s){
230                 case 0: /* both positive */
231                         bigint_add_u(dest, a,b);
232                         SET_POS(dest);
233                         break;
234                 case 1: /* a positive, b negative */
235                         bigint_sub_u(dest, a, b);
236                         break;
237                 case 2: /* a negative, b positive */
238                         bigint_sub_u(dest, b, a);
239                         break;
240                 case 3: /* both negative */
241                         bigint_add_u(dest, a, b);
242                         SET_NEG(dest);
243                         break;
244                 default: /* how can this happen?*/
245                         break;
246         }
247 }
248
249 /******************************************************************************/
250
251 void bigint_sub_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
252         uint8_t s;
253         s  = GET_SIGN(a)?2:0;
254         s |= GET_SIGN(b)?1:0;
255         switch(s){
256                 case 0: /* both positive */
257                         bigint_sub_u(dest, a,b);
258                         break;
259                 case 1: /* a positive, b negative */
260                         bigint_add_u(dest, a, b);
261                         SET_POS(dest);
262                         break;
263                 case 2: /* a negative, b positive */
264                         bigint_add_u(dest, a, b);
265                         SET_NEG(dest);
266                         break;
267                 case 3: /* both negative */
268                         bigint_sub_u(dest, b, a);
269                         break;
270                 default: /* how can this happen?*/
271                                         break;
272         }
273
274 }
275
276 /******************************************************************************/
277
278 int8_t bigint_cmp_s(const bigint_t* a, const bigint_t* b){
279         uint8_t s;
280         if(a->length_B==0 && b->length_B==0){
281                 return 0;
282         }
283         s  = GET_SIGN(a)?2:0;
284         s |= GET_SIGN(b)?1:0;
285         switch(s){
286                 case 0: /* both positive */
287                         return bigint_cmp_u(a, b);
288                         break;
289                 case 1: /* a positive, b negative */
290                         return 1;
291                         break;
292                 case 2: /* a negative, b positive */
293                         return -1;
294                         break;
295                 case 3: /* both negative */
296                         return bigint_cmp_u(b, a);
297                         break;
298                 default: /* how can this happen?*/
299                                         break;
300         }
301         return 0; /* just to satisfy the compiler */
302 }
303
304 /******************************************************************************/
305
306 void bigint_shiftleft(bigint_t* a, uint16_t shift){
307         uint16_t byteshift;
308         uint16_t i;
309         uint8_t bitshift;
310         uint16_t t=0;
311         byteshift = (shift+3)/8;
312         bitshift = shift&7;
313         memmove(a->wordv+byteshift, a->wordv, a->length_B);
314         memset(a->wordv, 0, byteshift);
315         if(bitshift!=0){
316                 if(bitshift<=4){ /* shift to the left */
317                         for(i=byteshift; i<a->length_B+byteshift; ++i){
318                                 t |= (a->wordv[i])<<bitshift;
319                                 a->wordv[i] = (uint8_t)t;
320                                 t >>= 8;
321                         }
322                         a->wordv[i] = (uint8_t)t;
323                         byteshift++;
324                 }else{ /* shift to the right */
325                         for(i=a->length_B+byteshift-1; i>byteshift-1; --i){
326                                 t |= (a->wordv[i])<<(bitshift);
327                                 a->wordv[i] = (uint8_t)(t>>8);
328                                 t <<= 8;
329                         }
330                         t |= (a->wordv[i])<<(bitshift);
331                         a->wordv[i] = (uint8_t)(t>>8);
332                 }
333         }
334         a->length_B += byteshift;
335         bigint_adjust(a);
336 }
337
338 /******************************************************************************/
339
340 void bigint_shiftright(bigint_t* a, uint16_t shift){
341         uint16_t byteshift;
342         uint16_t i;
343         uint8_t bitshift;
344         uint16_t t=0;
345         byteshift = shift/8;
346         bitshift = shift&7;
347         if(byteshift >= a->length_B){ /* we would shift out more than we have */
348                 bigint_set_zero(a);
349                 return;
350         }
351         if(byteshift == a->length_B-1 && bitshift>GET_FBS(a)){
352                 bigint_set_zero(a);
353                 return;
354         }
355         if(byteshift){
356                 memmove(a->wordv, a->wordv+byteshift, a->length_B-byteshift);
357                 memset(a->wordv+a->length_B-byteshift, 0,  byteshift);
358         }
359         if(bitshift!=0){
360          /* shift to the right */
361                 for(i=a->length_B-byteshift-1; i>0; --i){
362                         t |= (a->wordv[i])<<(8-bitshift);
363                         a->wordv[i] = (uint8_t)(t>>8);
364                         t <<= 8;
365                 }
366                 t |= (a->wordv[0])<<(8-bitshift);
367                 a->wordv[0] = (uint8_t)(t>>8);
368         }
369         a->length_B -= byteshift;
370         bigint_adjust(a);
371 }
372
373 /******************************************************************************/
374
375 void bigint_xor(bigint_t* dest, const bigint_t* a){
376         uint16_t i;
377         for(i=0; i<a->length_B; ++i){
378                 dest->wordv[i] ^= a->wordv[i];
379         }
380         bigint_adjust(dest);
381 }
382
383 /******************************************************************************/
384
385 void bigint_set_zero(bigint_t* a){
386         a->length_B=0;
387 }
388
389 /******************************************************************************/
390
391 /* using the Karatsuba-Algorithm */
392 /* x*y = (xh*yh)*b**2n + ((xh+xl)*(yh+yl) - xh*yh - xl*yl)*b**n + yh*yl */
393 void bigint_mul_u(bigint_t* dest, const bigint_t* a, const bigint_t* b){
394         if(dest==a || dest==b){
395                 bigint_t d;
396                 uint8_t d_b[a->length_B+b->length_B];
397                 d.wordv = d_b;
398                 bigint_mul_u(&d, a, b);
399                 bigint_copy(dest, &d);
400                 return;
401         }
402         if(a->length_B==0 || b->length_B==0){
403                 bigint_set_zero(dest);
404                 return;
405         }
406         if(a->length_B==1 || b->length_B==1){
407                 if(a->length_B!=1){
408                         XCHG_PTR(a,b);
409                 }
410                 uint16_t i, t=0;
411                 uint8_t x = a->wordv[0];
412                 for(i=0; i<b->length_B; ++i){
413                         t += b->wordv[i]*x;
414                         dest->wordv[i] = (uint8_t)t;
415                         t>>=8;
416                 }
417                 dest->wordv[i] = (uint8_t)t;
418                 dest->length_B=i+1;
419                 bigint_adjust(dest);
420                 return;
421         }
422         if(a->length_B<=4 && b->length_B<=4){
423                 uint32_t p=0, q=0;
424                 uint64_t r;
425                 memcpy(&p, a->wordv, a->length_B);
426                 memcpy(&q, b->wordv, b->length_B);
427                 r = (uint64_t)p*(uint64_t)q;
428                 memcpy(dest->wordv, &r, a->length_B+b->length_B);
429                 dest->length_B =  a->length_B+b->length_B;
430                 bigint_adjust(dest);
431                 return;
432         }
433         bigint_set_zero(dest);
434         /* split a in xh & xl; split b in yh & yl */
435         uint16_t n;
436         n=(MAX(a->length_B, b->length_B)+1)/2;
437         bigint_t xl, xh, yl, yh;
438         xl.wordv = a->wordv;
439         yl.wordv = b->wordv;
440         if(a->length_B<=n){
441                 xh.info=0;
442                 xh.length_B = 0;
443                 xl.length_B = a->length_B;
444                 xl.info = 0;
445         }else{
446                 xl.length_B=n;
447                 xl.info = 0;
448                 bigint_adjust(&xl);
449                 xh.wordv = a->wordv+n;
450                 xh.length_B = a->length_B-n;
451                 xh.info = 0;
452         }
453         if(b->length_B<=n){
454                 yh.info=0;
455                 yh.length_B = 0;
456                 yl.length_B = b->length_B;
457                 yl.info = b->info;
458         }else{
459                 yl.length_B=n;
460                 yl.info = 0;
461                 bigint_adjust(&yl);
462                 yh.wordv = b->wordv+n;
463                 yh.length_B = b->length_B-n;
464                 yh.info = 0;
465         }
466         /* now we have split up a and b */
467         uint8_t  tmp_b[2*n+2], m_b[2*(n+1)];
468         bigint_t tmp, tmp2, m;
469         tmp.wordv = tmp_b;
470         tmp2.wordv = tmp_b+n+1;
471         m.wordv = m_b;
472
473         bigint_mul_u(dest, &xl, &yl);  /* dest <= xl*yl     */
474         bigint_add_u(&tmp2, &xh, &xl); /* tmp2 <= xh+xl     */
475         bigint_add_u(&tmp, &yh, &yl);  /* tmp  <= yh+yl     */
476         bigint_mul_u(&m, &tmp2, &tmp); /* m    <= tmp2*tmp  */
477         bigint_mul_u(&tmp, &xh, &yh);  /* h    <= xh*yh     */
478         bigint_sub_u(&m, &m, dest);    /* m    <= m-dest    */
479     bigint_sub_u(&m, &m, &tmp);    /* m    <= m-h       */
480         bigint_add_scale_u(dest, &m, n);
481         bigint_add_scale_u(dest, &tmp, 2*n);
482 }
483
484 /******************************************************************************/
485
486 void bigint_mul_s(bigint_t* dest, const bigint_t* a, const bigint_t* b){
487         uint8_t s;
488         s  = GET_SIGN(a)?2:0;
489         s |= GET_SIGN(b)?1:0;
490         switch(s){
491                 case 0: /* both positive */
492                         bigint_mul_u(dest, a,b);
493                         SET_POS(dest);
494                         break;
495                 case 1: /* a positive, b negative */
496                         bigint_mul_u(dest, a,b);
497                         SET_NEG(dest);
498                         break;
499                 case 2: /* a negative, b positive */
500                         bigint_mul_u(dest, a,b);
501                         SET_NEG(dest);
502                         break;
503                 case 3: /* both negative */
504                         bigint_mul_u(dest, a,b);
505                         SET_POS(dest);
506                         break;
507                 default: /* how can this happen?*/
508                         break;
509         }
510 }
511
512 /******************************************************************************/
513
514 /* square */
515 /* (xh*b^n+xl)^2 = xh^2*b^2n + 2*xh*xl*b^n + xl^2 */
516 void bigint_square(bigint_t* dest, const bigint_t* a){
517         if(a->length_B<=4){
518                 uint64_t r=0;
519                 memcpy(&r, a->wordv, a->length_B);
520                 r = r*r;
521                 memcpy(dest->wordv, &r, 2*a->length_B);
522                 SET_POS(dest);
523                 dest->length_B=2*a->length_B;
524                 bigint_adjust(dest);
525                 return;
526         }
527         if(dest==a){
528                 bigint_t d;
529                 uint8_t d_b[a->length_B*2];
530                 d.wordv = d_b;
531                 bigint_square(&d, a);
532                 bigint_copy(dest, &d);
533                 return;
534         }
535         uint16_t n;
536         n=(a->length_B+1)/2;
537         bigint_t xh, xl, tmp; /* x-high, x-low, temp */
538         uint8_t buffer[2*n+1];
539         xl.wordv = a->wordv;
540         xl.length_B = n;
541         xh.wordv = a->wordv+n;
542         xh.length_B = a->length_B-n;
543         tmp.wordv = buffer;
544         bigint_square(dest, &xl);
545         bigint_square(&tmp, &xh);
546         bigint_add_scale_u(dest, &tmp, 2*n);
547         bigint_mul_u(&tmp, &xl, &xh);
548         bigint_shiftleft(&tmp, 1);
549         bigint_add_scale_u(dest, &tmp, n);
550 }
551
552 /******************************************************************************/
553
554 void bigint_sub_u_bitscale(bigint_t* a, const bigint_t* b, uint16_t bitscale){
555         bigint_t tmp;
556         uint8_t tmp_b[b->length_B+1];
557         uint16_t i,j,byteshift=bitscale/8;
558         uint8_t borrow=0;
559         int16_t t;
560
561         if(a->length_B < b->length_B+byteshift){
562                 cli_putstr_P(PSTR("\r\nERROR: bigint_sub_u_bitscale result negative"));
563                 bigint_set_zero(a);
564                 return;
565         }
566
567         tmp.wordv = tmp_b;
568         bigint_copy(&tmp, b);
569         bigint_shiftleft(&tmp, bitscale&7);
570
571         for(j=0,i=byteshift; i<tmp.length_B+byteshift; ++i, ++j){
572                 t = a->wordv[i] - tmp.wordv[j] - borrow;
573                 a->wordv[i] = (uint8_t)t;
574                 if(t<0){
575                         borrow = 1;
576                 }else{
577                         borrow = 0;
578                 }
579         }
580         while(borrow){
581                 if(i+1 > a->length_B){
582                         cli_putstr_P(PSTR("\r\nERROR: bigint_sub_u_bitscale result negative (2) shift="));
583                         cli_hexdump_rev(&bitscale, 2);
584                         bigint_set_zero(a);
585                         return;
586                 }
587                 a->wordv[i] -= borrow;
588                 if(a->wordv[i]!=0xff){
589                         borrow=0;
590                 }
591                 ++i;
592         }
593         bigint_adjust(a);
594 }
595
596 /******************************************************************************/
597
598 void bigint_reduce(bigint_t* a, const bigint_t* r){
599         uint8_t rfbs = GET_FBS(r);
600 /*
601         cli_putstr_P(PSTR("\r\nreduce "));
602         bigint_print_hex(a);
603         cli_putstr_P(PSTR(" % "));
604         bigint_print_hex(r);
605         cli_putstr_P(PSTR("\r\n"));
606 */
607
608         if(r->length_B==0){
609                 return;
610         }
611         while(a->length_B > r->length_B){
612                 bigint_sub_u_bitscale(a, r, (a->length_B-r->length_B)*8+GET_FBS(a)-rfbs-1);
613         }
614
615         while((GET_FBS(a) > rfbs+1) && (a->length_B == r->length_B)){
616                 bigint_sub_u_bitscale(a, r, GET_FBS(a)-rfbs-1);
617         }
618
619         while(bigint_cmp_u(a,r)>=0){
620                 bigint_sub_u(a,a,r);
621         }
622         bigint_adjust(a);
623 }
624
625 /******************************************************************************/
626
627 /* calculate dest = a**exp % r */
628 /* using square&multiply */
629 void bigint_expmod_u(bigint_t* dest, const bigint_t* a, const bigint_t* exp, const bigint_t* r){
630         bigint_t tmp, tmp2, x;
631         uint8_t x_b[MAX(r->length_B, a->length_B)], tmp_b[r->length_B*2], tmp2_b[r->length_B*2];
632         int16_t i;
633         uint8_t j;
634         x.wordv = x_b;
635         tmp.wordv = tmp_b;
636         tmp2.wordv = tmp2_b;
637         bigint_copy(&x, a);
638         bigint_reduce(&x, r);
639         bigint_copy(&tmp, &x);
640         if(a->length_B==0 || exp->length_B==0 || r->length_B==0){
641                 return;
642         }
643         i=exp->length_B-1;
644         if(exp->wordv[i]!=1){
645                 for(j=1<<(GET_FBS(exp)-1); j>0; j>>=1){
646         //              cli_putc('Q');
647                         bigint_square(&tmp2, &tmp);
648                         bigint_reduce(&tmp2, r);
649                         if(exp->wordv[i]&j){
650         //                      cli_putc('M');
651                                 bigint_mul_u(&tmp, &tmp2, &x);
652                                 bigint_reduce(&tmp, r);
653                         }else{
654                                 bigint_copy(&tmp, &tmp2);
655                         }
656                 }
657         }
658         for(--i; i>=0; --i){
659                 for(j=0x80; j>0; j>>=1){
660 //                      cli_putc('q');
661                         bigint_square(&tmp2, &tmp);
662                         bigint_reduce(&tmp2, r);
663                         if(exp->wordv[i]&j){
664 //                              cli_putc('m');
665                                 bigint_mul_u(&tmp, &tmp2, &x);
666                                 bigint_reduce(&tmp, r);
667                         }else{
668                                 bigint_copy(&tmp, &tmp2);
669                         }
670                 }
671         }
672 //      cli_putstr_P(PSTR("\r\n"));
673         bigint_copy(dest, &tmp);
674 }
675 #define DEBUG 0
676 /******************************************************************************/
677 /* gcd <-- gcd(x,y) a*x+b*y=gcd */
678 void bigint_gcdext(bigint_t* gcd, bigint_t* a, bigint_t* b, const bigint_t* x, const bigint_t* y){
679          bigint_t g, x_, y_, u, v, a_, b_, c_, d_;
680          volatile uint16_t i=0;
681          if(x->length_B==0 || y->length_B==0){
682                  return;
683          }
684          while(x->wordv[i]==0 && y->wordv[i]==0){
685                  ++i;
686          }
687          uint8_t g_b[i+2], x_b[x->length_B-i], y_b[y->length_B-i];
688          uint8_t u_b[x->length_B-i], v_b[y->length_B-i];
689          uint8_t a_b[y->length_B+2], c_b[y->length_B+2];
690          uint8_t b_b[x->length_B+2], d_b[x->length_B+2];
691
692          g.wordv = g_b;
693          x_.wordv = x_b;
694          y_.wordv = y_b;
695          memset(g_b, 0, i);
696          g_b[i]=1;
697          g.length_B = i+1;
698          g.info=0;
699          x_.info = y_.info = 0;
700          x_.length_B = x->length_B-i;
701          y_.length_B = y->length_B-i;
702          memcpy(x_.wordv, x->wordv+i, x_.length_B);
703          memcpy(y_.wordv, y->wordv+i, y_.length_B);
704          for(i=0; (x_.wordv[0]&(1<<i))==0 && (y_.wordv[0]&(1<<i))==0; ++i){
705          }
706
707 #if DEBUG
708          cli_putstr_P(PSTR("\r\nDBG: initshift = "));
709          cli_hexdump_rev(&i, 2);
710 #endif
711          bigint_adjust(&x_);
712          bigint_adjust(&y_);
713
714          if(i){
715                  bigint_shiftleft(&g, i);
716 #if DEBUG
717          cli_putstr_P(PSTR("\r\nDBG: initshift (2) = "));
718          cli_hexdump_rev(&i, 2);
719          cli_putstr_P(PSTR("\r\n x' = "));
720                 bigint_print_hex(&x_);
721                 cli_putstr_P(PSTR("\r\n y' = "));
722                 bigint_print_hex(&y_);
723 #endif
724                 bigint_shiftright(&x_, i);
725                 bigint_shiftright(&y_, i);
726 #if DEBUG
727                 cli_putstr_P(PSTR("\r\n x' = "));
728                 bigint_print_hex(&x_);
729                 cli_putstr_P(PSTR("\r\n y' = "));
730                 bigint_print_hex(&y_);
731 #endif
732          }
733          u.wordv = u_b;
734          v.wordv = v_b;
735          a_.wordv = a_b;
736          b_.wordv = b_b;
737          c_.wordv = c_b;
738          d_.wordv = d_b;
739
740          bigint_copy(&u, &x_);
741          bigint_copy(&v, &y_);
742          a_.wordv[0] = 1;
743          a_.length_B = 1;
744          a_.info = 0;
745          d_.wordv[0] = 1;
746          d_.length_B = 1;
747          d_.info = 0;
748          bigint_set_zero(&b_);
749          bigint_set_zero(&c_);
750          do{
751 #if DEBUG
752                  cli_putstr_P(PSTR("\r\n while u%2==0; u = "));
753                  bigint_print_hex(&u);
754                  cli_putstr_P(PSTR("\r\nDBG: (10) a = "));
755                  bigint_print_hex(&a_);
756                  cli_putstr_P(PSTR("\r\nDBG: (10) b = "));
757                  bigint_print_hex(&b_);
758                  cli_putstr_P(PSTR("\r\nDBG: (10) c = "));
759                  bigint_print_hex(&c_);
760                  cli_putstr_P(PSTR("\r\nDBG: (10) d = "));
761                  bigint_print_hex(&d_);
762 #endif
763                  while((u.wordv[0]&1)==0){
764                          bigint_shiftright(&u, 1);
765                          if((a_.wordv[0]&1) || (b_.wordv[0]&1)){
766                                  bigint_add_s(&a_, &a_, &y_);
767                                  bigint_sub_s(&b_, &b_, &x_);
768                          }
769                          bigint_shiftright(&a_, 1);
770                          bigint_shiftright(&b_, 1);
771                  }
772 #if DEBUG
773                  cli_putstr_P(PSTR("\r\n while v%2==0; v = "));
774                  bigint_print_hex(&v);
775                  cli_putstr_P(PSTR("\r\nDBG: (20) a = "));
776                  bigint_print_hex(&a_);
777                  cli_putstr_P(PSTR("\r\nDBG: (20) b = "));
778                  bigint_print_hex(&b_);
779                  cli_putstr_P(PSTR("\r\nDBG: (20) c = "));
780                  bigint_print_hex(&c_);
781                  cli_putstr_P(PSTR("\r\nDBG: (20) d = "));
782                  bigint_print_hex(&d_);
783 #endif
784                  while((v.wordv[0]&1)==0){
785                          bigint_shiftright(&v, 1);
786                          if((c_.wordv[0]&1) || (d_.wordv[0]&1)){
787                                  bigint_add_s(&c_, &c_, &y_);
788                                  bigint_sub_s(&d_, &d_, &x_);
789                          }
790                          bigint_shiftright(&c_, 1);
791                          bigint_shiftright(&d_, 1);
792
793                  }
794 #if DEBUG
795                  cli_putstr_P(PSTR("\r\n if u>=v ..."));
796                  cli_putstr_P(PSTR("\r\nDBG: (30) a = "));
797                  bigint_print_hex(&a_);
798                  cli_putstr_P(PSTR("\r\nDBG: (30) b = "));
799                  bigint_print_hex(&b_);
800                  cli_putstr_P(PSTR("\r\nDBG: (30) c = "));
801                  bigint_print_hex(&c_);
802                  cli_putstr_P(PSTR("\r\nDBG: (30) d = "));
803                  bigint_print_hex(&d_);
804 #endif
805                  if(bigint_cmp_u(&u, &v)>=0){
806                         bigint_sub_u(&u, &u, &v);
807                         bigint_sub_s(&a_, &a_, &c_);
808                         bigint_sub_s(&b_, &b_, &d_);
809                  }else{
810                         bigint_sub_u(&v, &v, &u);
811                         bigint_sub_s(&c_, &c_, &a_);
812                         bigint_sub_s(&d_, &d_, &b_);
813                  }
814 #if DEBUG
815                  if(GET_SIGN(&u)){
816                          cli_putstr_P(PSTR("\r\nDBG: u negative! u = "));
817                          bigint_print_hex(&u);
818                  }
819                  if(GET_SIGN(&v)){
820                          cli_putstr_P(PSTR("\r\nDBG: v negative! v = "));
821                          bigint_print_hex(&v);
822                  }
823 #endif
824 /*
825                  cli_putstr_P(PSTR("\r\nDBG: (2) a = "));
826                  bigint_print_hex(&a_);
827                  cli_putstr_P(PSTR("\r\nDBG: (2) b = "));
828                  bigint_print_hex(&b_);
829                  cli_putstr_P(PSTR("\r\nDBG: (2) c = "));
830                  bigint_print_hex(&c_);
831                  cli_putstr_P(PSTR("\r\nDBG: (2) d = "));
832                  bigint_print_hex(&d_);
833 */
834          }while(u.length_B);
835          if(gcd){
836                  bigint_mul_s(gcd, &v, &g);
837          }
838          if(a){
839                 bigint_copy(a, &c_);
840          }
841          if(b){
842                  bigint_copy(b, &d_);
843          }
844 }
845
846 /******************************************************************************/
847
848 void bigint_inverse(bigint_t* dest, bigint_t* a, bigint_t* m){
849         bigint_gcdext(NULL, dest, NULL, a, m);
850         while(dest->info&BIGINT_NEG_MASK){
851                 bigint_add_s(dest, dest, m);
852         }
853 }
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878