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